1
1
using System ;
2
2
using System . Diagnostics ;
3
- using System . Text ;
4
3
using System . Threading ;
5
- using System . Threading . Tasks ;
6
4
using ServiceStack . Logging ;
7
5
using ServiceStack . Text ;
8
6
@@ -34,6 +32,7 @@ public class RedisPubSubServer : IRedisPubSubServer
34
32
35
33
public Action < string > OnControlCommand { get ; set ; }
36
34
public Action < string > OnUnSubscribe { get ; set ; }
35
+ public Action < string > OnEvent { get ; set ; }
37
36
public Action < Exception > OnError { get ; set ; }
38
37
public Action < IRedisPubSubServer > OnFailover { get ; set ; }
39
38
public bool IsSentinelSubscription { get ; set ; }
@@ -97,6 +96,8 @@ public IRedisPubSubServer Start()
97
96
//Only 1 thread allowed past
98
97
if ( Interlocked . CompareExchange ( ref status , Status . Starting , Status . Stopped ) == Status . Stopped ) //Should only be 1 thread past this point
99
98
{
99
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} Stopped] Start()> Stopped -> Starting") ;
100
+
100
101
var initErrors = 0 ;
101
102
bool hasInit = false ;
102
103
while ( ! hasInit )
@@ -108,6 +109,7 @@ public IRedisPubSubServer Start()
108
109
}
109
110
catch ( Exception ex )
110
111
{
112
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] Start().Init()> Exception: { ex . Message } ") ;
111
113
OnError ? . Invoke ( ex ) ;
112
114
SleepBackOffMultiplier ( initErrors ++ ) ;
113
115
}
@@ -188,6 +190,8 @@ void SendHeartbeat(object state)
188
190
if ( DateTime . UtcNow - new DateTime ( lastHeartbeatTicks ) > HeartbeatTimeout )
189
191
{
190
192
currentStatus = Interlocked . CompareExchange ( ref status , 0 , 0 ) ;
193
+
194
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { Status . GetStatus ( currentStatus ) } ] SendHeartbeat()> Exceeded HeartbeatTimeout") ;
191
195
if ( currentStatus == Status . Started )
192
196
{
193
197
Restart ( ) ;
@@ -210,7 +214,7 @@ private void DisposeHeartbeatTimer()
210
214
try
211
215
{
212
216
if ( Log . IsDebugEnabled )
213
- Log . DebugFormat ( "RedisPubServer.DisposeHeartbeatTimer()" ) ;
217
+ Log . Debug ( "RedisPubServer.DisposeHeartbeatTimer()" ) ;
214
218
215
219
heartbeatTimer . Dispose ( ) ;
216
220
}
@@ -227,6 +231,8 @@ private void RunLoop()
227
231
if ( Interlocked . CompareExchange ( ref status , Status . Started , Status . Starting ) != Status . Starting ) return ;
228
232
Interlocked . Increment ( ref timesStarted ) ;
229
233
234
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} Started] RunLoop().Stop> Starting -> Started, timesStarted: { timesStarted } ") ;
235
+
230
236
try
231
237
{
232
238
//RESET
@@ -280,22 +286,31 @@ bool IsCtrlMessage(byte[] msg)
280
286
if ( Log . IsDebugEnabled )
281
287
Log . Debug ( "Stop Command Issued" ) ;
282
288
289
+ var holdStatus = GetStatus ( ) ;
290
+
283
291
Interlocked . CompareExchange ( ref status , Status . Stopping , Status . Started ) ;
292
+
293
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { holdStatus } ] RunLoop().Stop> Started -> Stopping") ;
284
294
try
285
295
{
286
296
if ( Log . IsDebugEnabled )
287
297
Log . Debug ( "UnSubscribe From All Channels..." ) ;
288
298
299
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] RunLoop().Stop> subscription.UnSubscribeFromAllChannels()") ;
300
+
289
301
// ReSharper disable once AccessToDisposedClosure
290
302
subscription . UnSubscribeFromAllChannels ( ) ; //Un block thread.
291
303
}
292
304
finally
293
305
{
306
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] RunLoop().Stop> Stopping -> Stopped") ;
294
307
Interlocked . CompareExchange ( ref status , Status . Stopped , Status . Stopping ) ;
295
308
}
296
309
return ;
297
310
298
311
case Operation . Reset :
312
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] RunLoop().Reset> subscription.UnSubscribeFromAllChannels()") ;
313
+
299
314
// ReSharper disable once AccessToDisposedClosure
300
315
subscription . UnSubscribeFromAllChannels ( ) ; //Un block thread.
301
316
return ;
@@ -330,10 +345,14 @@ bool IsCtrlMessage(byte[] msg)
330
345
lastExMsg = ex . Message ;
331
346
Interlocked . Increment ( ref noOfErrors ) ;
332
347
Interlocked . Increment ( ref noOfContinuousErrors ) ;
348
+
349
+ var holdStatus = GetStatus ( ) ;
333
350
334
351
if ( Interlocked . CompareExchange ( ref status , Status . Stopped , Status . Started ) != Status . Started )
335
352
Interlocked . CompareExchange ( ref status , Status . Stopped , Status . Stopping ) ;
336
353
354
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { holdStatus } ] RunLoop().Stop> Started|Stopping -> Stopped") ;
355
+
337
356
OnStop ? . Invoke ( ) ;
338
357
339
358
OnError ? . Invoke ( ex ) ;
@@ -343,6 +362,8 @@ bool IsCtrlMessage(byte[] msg)
343
362
{
344
363
if ( WaitBeforeNextRestart != null )
345
364
TaskUtils . Sleep ( WaitBeforeNextRestart . Value ) ;
365
+
366
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] RunLoop().AutoRestart> Start()") ;
346
367
Start ( ) ;
347
368
}
348
369
}
@@ -361,6 +382,8 @@ private void Stop(bool shouldRestart)
361
382
362
383
if ( Interlocked . CompareExchange ( ref status , Status . Stopping , Status . Started ) == Status . Started )
363
384
{
385
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] Stop()> Started -> Stopping") ;
386
+
364
387
if ( Log . IsDebugEnabled )
365
388
Log . Debug ( "Stopping RedisPubSubServer..." ) ;
366
389
@@ -392,7 +415,7 @@ private void NotifyAllSubscribers(string commandType=null)
392
415
catch ( Exception ex )
393
416
{
394
417
OnError ? . Invoke ( ex ) ;
395
- Log . Warn ( "Could not send '{0}' message to bg thread: {1}" . Fmt ( msg , ex . Message ) ) ;
418
+ Log . WarnFormat ( "Could not send '{0}' message to bg thread: {1}" , msg , ex . Message ) ;
396
419
}
397
420
}
398
421
@@ -447,10 +470,12 @@ private void KillBgThreadIfExists()
447
470
{
448
471
#if ! NETSTANDARD2_0
449
472
//Ideally we shouldn't get here, but lets try our hardest to clean it up
473
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] KillBgThreadIfExists()> bgThread.Interrupt()") ;
450
474
Log . Warn ( "Interrupting previous Background Thread: " + bgThread . Name ) ;
451
475
bgThread . Interrupt ( ) ;
452
476
if ( ! bgThread . Join ( TimeSpan . FromSeconds ( 3 ) ) )
453
477
{
478
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] KillBgThreadIfExists()> bgThread.Abort()") ;
454
479
Log . Warn ( bgThread . Name + " just wont die, so we're now aborting it..." ) ;
455
480
bgThread . Abort ( ) ;
456
481
}
@@ -471,7 +496,7 @@ private void SleepBackOffMultiplier(int continuousErrorsCount)
471
496
maxSleepMs ) ;
472
497
473
498
if ( Log . IsDebugEnabled )
474
- Log . Debug ( "Sleeping for {0}ms after {1} continuous errors" . Fmt ( nextTry , continuousErrorsCount ) ) ;
499
+ Log . DebugFormat ( "Sleeping for {0}ms after {1} continuous errors" , nextTry , continuousErrorsCount ) ;
475
500
476
501
TaskUtils . Sleep ( nextTry ) ;
477
502
}
@@ -514,26 +539,22 @@ class Status //dep-free copy of WorkerStatus
514
539
public const int Stopping = 1 ;
515
540
public const int Starting = 2 ;
516
541
public const int Started = 3 ;
517
- }
518
542
519
- public string GetStatus ( )
520
- {
521
- switch ( Interlocked . CompareExchange ( ref status , 0 , 0 ) )
543
+ public static string GetStatus ( int status )
522
544
{
523
- case Status . Disposed :
524
- return "Disposed" ;
525
- case Status . Stopped :
526
- return "Stopped" ;
527
- case Status . Stopping :
528
- return "Stopping" ;
529
- case Status . Starting :
530
- return "Starting" ;
531
- case Status . Started :
532
- return "Started" ;
545
+ return status switch {
546
+ Disposed => nameof ( Disposed ) ,
547
+ Stopped => nameof ( Stopped ) ,
548
+ Stopping => nameof ( Stopping ) ,
549
+ Starting => nameof ( Starting ) ,
550
+ Started => nameof ( Started ) ,
551
+ _ => throw new NotSupportedException ( "Unknown status: " + status )
552
+ } ;
533
553
}
534
- return null ;
535
554
}
536
555
556
+ public string GetStatus ( ) => Status . GetStatus ( Interlocked . CompareExchange ( ref status , 0 , 0 ) ) ;
557
+
537
558
public string GetStatsDescription ( )
538
559
{
539
560
var sb = StringBuilderCache . Allocate ( ) ;
@@ -555,11 +576,17 @@ public virtual void Dispose()
555
576
if ( Log . IsDebugEnabled )
556
577
Log . Debug ( "RedisPubServer.Dispose()..." ) ;
557
578
579
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { GetStatus ( ) } ] Dispose()>") ;
580
+
558
581
Stop ( ) ;
559
582
583
+ var holdStatus = GetStatus ( ) ;
584
+
560
585
if ( Interlocked . CompareExchange ( ref status , Status . Disposed , Status . Stopped ) != Status . Stopped )
561
586
Interlocked . CompareExchange ( ref status , Status . Disposed , Status . Stopping ) ;
562
587
588
+ OnEvent ? . Invoke ( $ "[{ DateTime . UtcNow . TimeOfDay : g} { holdStatus } ] Dispose()> -> Disposed") ;
589
+
563
590
try
564
591
{
565
592
OnDispose ? . Invoke ( ) ;
0 commit comments