-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add FbClientStatus * add StatusManagerTests * add AtomicBooleanTests.cs * use AtomicBoolean * set status to stable when we handle message successfully * no need to subscribe to reconnected event * update comment * set status to Stable only when handle data-sync message success * update comment * update * chore * remove status manager for FbClient * more work * more test * fix test * add health check example * add missing changes
- Loading branch information
1 parent
1845c69
commit cfa28a8
Showing
17 changed files
with
475 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using FeatBit.Sdk.Server; | ||
using Microsoft.Extensions.Diagnostics.HealthChecks; | ||
|
||
namespace WebApiApp; | ||
|
||
public class FeatBitHealthCheck : IHealthCheck | ||
{ | ||
private readonly IFbClient _fbClient; | ||
|
||
public FeatBitHealthCheck(IFbClient fbClient) | ||
{ | ||
_fbClient = fbClient; | ||
} | ||
|
||
public Task<HealthCheckResult> CheckHealthAsync( | ||
HealthCheckContext context, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var status = _fbClient.Status; | ||
|
||
var result = status switch | ||
{ | ||
FbClientStatus.Ready => HealthCheckResult.Healthy(), | ||
FbClientStatus.Stale => HealthCheckResult.Degraded(), | ||
_ => HealthCheckResult.Unhealthy() | ||
}; | ||
|
||
return Task.FromResult(result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace FeatBit.Sdk.Server.Concurrent; | ||
|
||
public sealed class StatusManager<TStatus> where TStatus : Enum | ||
{ | ||
private TStatus _status; | ||
private readonly object _statusLock = new object(); | ||
private readonly Action<TStatus> _onStatusChanged; | ||
|
||
public StatusManager(TStatus initialStatus, Action<TStatus> onStatusChanged = null) | ||
{ | ||
_status = initialStatus; | ||
_onStatusChanged = onStatusChanged; | ||
} | ||
|
||
public TStatus Status | ||
{ | ||
get | ||
{ | ||
lock (_statusLock) | ||
{ | ||
return _status; | ||
} | ||
} | ||
} | ||
|
||
public bool CompareAndSet(TStatus expected, TStatus newStatus) | ||
{ | ||
lock (_statusLock) | ||
{ | ||
if (!EqualityComparer<TStatus>.Default.Equals(_status, expected)) | ||
{ | ||
return false; | ||
} | ||
|
||
SetStatus(newStatus); | ||
return true; | ||
} | ||
} | ||
|
||
public void SetStatus(TStatus newStatus) | ||
{ | ||
lock (_statusLock) | ||
{ | ||
if (EqualityComparer<TStatus>.Default.Equals(_status, newStatus)) | ||
{ | ||
return; | ||
} | ||
|
||
_status = newStatus; | ||
_onStatusChanged?.Invoke(_status); | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
src/FeatBit.ServerSdk/DataSynchronizer/DataSynchronizerStatus.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
namespace FeatBit.Sdk.Server.DataSynchronizer; | ||
|
||
public enum DataSynchronizerStatus | ||
{ | ||
/// <summary> | ||
/// The initial state of the synchronizer when the SDK is being initialized. | ||
/// </summary> | ||
/// <remarks> | ||
/// If it encounters an error that requires it to retry initialization, the state will remain at | ||
/// <see cref="Starting"/> until it either succeeds and becomes <see cref="Stable"/>, or | ||
/// permanently fails and becomes <see cref="Stopped"/>. | ||
/// </remarks> | ||
Starting, | ||
|
||
/// <summary> | ||
/// Indicates that the synchronizer is currently operational and has not had any problems since the | ||
/// last time it received data. | ||
/// </summary> | ||
/// <remarks> | ||
/// In streaming mode, this means that there is currently an open stream connection and that at least | ||
/// one initial message has been received on the stream. In polling mode, it means that the last poll | ||
/// request succeeded. | ||
/// </remarks> | ||
Stable, | ||
|
||
/// <summary> | ||
/// Indicates that the synchronizer encountered an error that it will attempt to recover from. | ||
/// </summary> | ||
/// <remarks> | ||
/// In streaming mode, this means that the stream connection failed, or had to be dropped due to some | ||
/// other error, and will be retried after a backoff delay. In polling mode, it means that the last poll | ||
/// request failed, and a new poll request will be made after the configured polling interval. | ||
/// </remarks> | ||
Interrupted, | ||
|
||
/// <summary> | ||
/// Indicates that the synchronizer has been permanently shut down. | ||
/// </summary> | ||
/// <remarks> | ||
/// This could be because it encountered an unrecoverable error (for instance, the Evaluation server | ||
/// rejected the SDK key: an invalid SDK key will never become valid), or because the SDK client was | ||
/// explicitly shut down. | ||
/// </remarks> | ||
Stopped | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/FeatBit.ServerSdk/DataSynchronizer/NullDataSynchronizer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,36 @@ | ||
using System; | ||
using System.Threading.Tasks; | ||
using FeatBit.Sdk.Server.Concurrent; | ||
|
||
namespace FeatBit.Sdk.Server.DataSynchronizer; | ||
|
||
internal sealed class NullDataSynchronizer : IDataSynchronizer | ||
{ | ||
private readonly StatusManager<DataSynchronizerStatus> _statusManager; | ||
|
||
public bool Initialized => true; | ||
public DataSynchronizerStatus Status => _statusManager.Status; | ||
public event Action<DataSynchronizerStatus> StatusChanged; | ||
|
||
public NullDataSynchronizer() | ||
{ | ||
_statusManager = new StatusManager<DataSynchronizerStatus>( | ||
DataSynchronizerStatus.Stable, | ||
OnStatusChanged | ||
); | ||
} | ||
|
||
public Task<bool> StartAsync() | ||
{ | ||
_statusManager.SetStatus(DataSynchronizerStatus.Stable); | ||
return Task.FromResult(true); | ||
} | ||
|
||
public Task StopAsync() | ||
{ | ||
_statusManager.SetStatus(DataSynchronizerStatus.Stopped); | ||
return Task.CompletedTask; | ||
} | ||
|
||
private void OnStatusChanged(DataSynchronizerStatus status) => StatusChanged?.Invoke(status); | ||
} |
Oops, something went wrong.