1- using System ;
1+ using System ;
22using System . Collections . Generic ;
33using System . Collections . Immutable ;
44using System . IO ;
@@ -23,6 +23,7 @@ internal sealed class FileDataSource : IDataSource
2323 private readonly FileDataTypes . IFileReader _fileReader ;
2424 private readonly bool _skipMissingPaths ;
2525 private readonly Logger _logger ;
26+ private readonly object _loadLock = new object ( ) ;
2627 private volatile bool _started ;
2728 private volatile bool _loadedValidData ;
2829 private volatile int _lastVersion ;
@@ -88,35 +89,38 @@ private void Dispose(bool disposing)
8889
8990 private void LoadAll ( )
9091 {
91- var version = Interlocked . Increment ( ref _lastVersion ) ;
92- var flags = new Dictionary < string , ItemDescriptor > ( ) ;
93- var segments = new Dictionary < string , ItemDescriptor > ( ) ;
94- foreach ( var path in _paths )
92+ lock ( _loadLock )
9593 {
96- try
97- {
98- var content = _fileReader . ReadAllText ( path ) ;
99- _logger . Debug ( "file data: {0}" , content ) ;
100- var data = _parser . Parse ( content , version ) ;
101- _dataMerger . AddToData ( data , flags , segments ) ;
102- }
103- catch ( FileNotFoundException ) when ( _skipMissingPaths )
94+ var version = Interlocked . Increment ( ref _lastVersion ) ;
95+ var flags = new Dictionary < string , ItemDescriptor > ( ) ;
96+ var segments = new Dictionary < string , ItemDescriptor > ( ) ;
97+ foreach ( var path in _paths )
10498 {
105- _logger . Debug ( "{0}: {1}" , path , "File not found" ) ;
106- }
107- catch ( Exception e )
108- {
109- LogHelpers . LogException ( _logger , "Failed to load " + path , e ) ;
110- return ;
99+ try
100+ {
101+ var content = _fileReader . ReadAllText ( path ) ;
102+ _logger . Debug ( "file data: {0}" , content ) ;
103+ var data = _parser . Parse ( content , version ) ;
104+ _dataMerger . AddToData ( data , flags , segments ) ;
105+ }
106+ catch ( FileNotFoundException ) when ( _skipMissingPaths )
107+ {
108+ _logger . Debug ( "{0}: {1}" , path , "File not found" ) ;
109+ }
110+ catch ( Exception e )
111+ {
112+ LogHelpers . LogException ( _logger , "Failed to load " + path , e ) ;
113+ return ;
114+ }
111115 }
116+ var allData = new FullDataSet < ItemDescriptor > (
117+ ImmutableDictionary . Create < DataKind , KeyedItems < ItemDescriptor > > ( )
118+ . SetItem ( DataModel . Features , new KeyedItems < ItemDescriptor > ( flags ) )
119+ . SetItem ( DataModel . Segments , new KeyedItems < ItemDescriptor > ( segments ) )
120+ ) ;
121+ _dataSourceUpdates . Init ( allData ) ;
122+ _loadedValidData = true ;
112123 }
113- var allData = new FullDataSet < ItemDescriptor > (
114- ImmutableDictionary . Create < DataKind , KeyedItems < ItemDescriptor > > ( )
115- . SetItem ( DataModel . Features , new KeyedItems < ItemDescriptor > ( flags ) )
116- . SetItem ( DataModel . Segments , new KeyedItems < ItemDescriptor > ( segments ) )
117- ) ;
118- _dataSourceUpdates . Init ( allData ) ;
119- _loadedValidData = true ;
120124 }
121125
122126 private void TriggerReload ( )
@@ -183,10 +187,15 @@ internal sealed class FileWatchingReloader : IDisposable
183187 private readonly ISet < string > _filePaths ;
184188 private readonly Action _reload ;
185189 private readonly List < FileSystemWatcher > _watchers ;
190+ private readonly Timer _debounceTimer ;
191+ private readonly int _debounceMillis ;
192+ private readonly object _timerLock = new object ( ) ;
186193
187- public FileWatchingReloader ( List < string > paths , Action reload )
194+ public FileWatchingReloader ( List < string > paths , Action reload , int debounceMillis = 100 )
188195 {
189196 _reload = reload ;
197+ _debounceMillis = debounceMillis ;
198+ _debounceTimer = new Timer ( OnDebounceTimerElapsed , null , Timeout . Infinite , Timeout . Infinite ) ;
190199
191200 _filePaths = new HashSet < string > ( ) ;
192201 var dirPaths = new HashSet < string > ( ) ;
@@ -216,10 +225,19 @@ private void ChangedPath(string path)
216225 {
217226 if ( _filePaths . Contains ( path ) )
218227 {
219- _reload ( ) ;
228+ lock ( _timerLock )
229+ {
230+ // Reset the timer to debounce multiple rapid file changes
231+ _debounceTimer . Change ( _debounceMillis , Timeout . Infinite ) ;
232+ }
220233 }
221234 }
222235
236+ private void OnDebounceTimerElapsed ( object state )
237+ {
238+ _reload ( ) ;
239+ }
240+
223241 public void Dispose ( )
224242 {
225243 Dispose ( true ) ;
@@ -229,6 +247,7 @@ private void Dispose(bool disposing)
229247 {
230248 if ( disposing )
231249 {
250+ _debounceTimer ? . Dispose ( ) ;
232251 foreach ( var w in _watchers )
233252 {
234253 w . Dispose ( ) ;
0 commit comments