@@ -15,14 +15,47 @@ public interface IJsonStorageAreaObserver : IJsonDocumentSource
15
15
string AreaName { get ; }
16
16
}
17
17
18
+ internal class Atomic < T >
19
+ {
20
+ private T value ;
21
+ private readonly object padlock = new ( ) ;
22
+
23
+ public Atomic ( T value )
24
+ {
25
+ this . value = value ;
26
+ }
27
+
28
+ public T Read ( ) {
29
+ lock ( padlock )
30
+ {
31
+ return value ;
32
+ }
33
+ }
34
+
35
+ public T Exchange ( T value )
36
+ {
37
+ lock ( padlock )
38
+ {
39
+ T current = this . value ;
40
+ this . value = value ;
41
+ return current ;
42
+ }
43
+ }
44
+
45
+ public static implicit operator Atomic < T > ( T value ) => new ( value ) ;
46
+ public static implicit operator T ( Atomic < T > value ) => value . Read ( ) ;
47
+ }
48
+
49
+
18
50
public class JsonStorageAreaObserver : IJsonStorageAreaObserver
19
51
{
20
52
private readonly string pollInterval ;
21
53
private readonly IWebTaskScheduler scheduler ;
22
54
private readonly IStorageAreaLog log ;
23
55
private readonly DocumentChangesStream observable = new ( ) ;
24
56
private readonly IInfoStream < JsonStorageAreaObserver > infoStream = new InfoStream < JsonStorageAreaObserver > ( ) ;
25
-
57
+ private readonly Atomic < bool > started = false ;
58
+
26
59
private long generation = 0 ;
27
60
private long initialGeneration = 0 ;
28
61
private IScheduledTask task ;
@@ -41,19 +74,25 @@ public JsonStorageAreaObserver(IStorageArea storageArea, IWebTaskScheduler sched
41
74
log = storageArea . Log ;
42
75
}
43
76
44
- public async Task RunAsync ( )
77
+ public async Task StartAsync ( )
45
78
{
79
+ if ( started . Exchange ( true ) )
80
+ return ;
81
+
46
82
infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Starting , StorageArea . Name , $ "Ingest starting for storageArea '{ StorageArea . Name } '.") ;
47
83
task = scheduler . Schedule ( $ "JsonStorageAreaObserver:{ StorageArea . Name } ", _ => RunUpdateCheck ( ) , pollInterval ) ;
48
84
task . InfoStream . Subscribe ( infoStream ) ;
49
- await task . WhenCompleted ( ) ;
85
+ await task . Signal ( true ) ;
50
86
}
51
87
52
88
public async Task StopAsync ( )
53
89
{
90
+ if ( ! started . Exchange ( false ) )
91
+ return ;
92
+
54
93
task . Dispose ( ) ;
55
- await task . WhenCompleted ( ) ;
56
- infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Stopped , StorageArea . Name , $ "Initializing for storageArea '{ StorageArea . Name } '.") ;
94
+ await task . WhenCompleted ( ) . ConfigureAwait ( false ) ;
95
+ infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Stopped , StorageArea . Name , $ "Stopping for storageArea '{ StorageArea . Name } '.") ;
57
96
}
58
97
59
98
public void UpdateGeneration ( string area , long value )
@@ -70,7 +109,6 @@ public async Task ResetAsync()
70
109
{
71
110
UpdateGeneration ( AreaName , initialGeneration ) ;
72
111
observable . Publish ( new JsonDocumentSourceReset ( AreaName ) ) ;
73
- task . Signal ( ) ;
74
112
}
75
113
76
114
public void RunUpdateCheck ( )
@@ -80,23 +118,19 @@ public void RunUpdateCheck()
80
118
Stopwatch timer = Stopwatch . StartNew ( ) ;
81
119
if ( ! Initialized . Value )
82
120
{
83
- BeforeInitialize ( ) ;
84
121
infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Initializing , StorageArea . Name , $ "Initializing for storageArea '{ StorageArea . Name } '.") ;
85
122
using IStorageAreaLogReader changes = log . OpenLogReader ( generation , Initialized . Value ) ;
86
123
PublishChanges ( changes , row => new JsonDocumentCreated ( row . Area , row . CreateEntity ( ) , row . Size , new GenerationInfo ( row . Generation , latestGeneration ) ) ) ;
87
124
Initialized . Value = true ;
88
125
infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Initialized , StorageArea . Name , $ "Initialization complete for storageArea '{ StorageArea . Name } ' in { timer . Elapsed } .") ;
89
- AfterInitialize ( ) ;
90
126
91
127
}
92
128
else
93
129
{
94
- BeforeUpdate ( ) ;
95
130
infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Updating , StorageArea . Name , $ "Checking updates for storageArea '{ StorageArea . Name } '.") ;
96
131
using IStorageAreaLogReader changes = log . OpenLogReader ( generation , Initialized . Value ) ;
97
132
PublishChanges ( changes , MapRow ) ;
98
133
infoStream . WriteJsonSourceEvent ( JsonSourceEventType . Updated , StorageArea . Name , $ "Done checking updates for storageArea '{ StorageArea . Name } ' in { timer . Elapsed } .") ;
99
- AfterUpdate ( ) ;
100
134
}
101
135
PublishCommitSignal ( ) ;
102
136
@@ -128,9 +162,4 @@ void PublishChanges(IStorageAreaLogReader changes, Func<IChangeLogRow, IJsonDocu
128
162
}
129
163
}
130
164
}
131
- public virtual void BeforeInitialize ( ) { }
132
- public virtual void AfterInitialize ( ) { }
133
-
134
- public virtual void BeforeUpdate ( ) { }
135
- public virtual void AfterUpdate ( ) { }
136
165
}
0 commit comments