Skip to content

Commit bef249c

Browse files
committed
TimeProvider 2
1 parent 7ea617d commit bef249c

12 files changed

Lines changed: 46 additions & 27 deletions

File tree

src/CasCap.Api.Buderus.Sinks/Services/Sinks/BuderusSinkAzTablesService.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace CasCap.Services;
99
public class BuderusSinkAzTablesService : IEventSink<BuderusEvent>, IBuderusQuery
1010
{
1111
private readonly ILogger _logger;
12+
private readonly TimeProvider _timeProvider;
1213
private readonly TableClient _lineItemTableClient;
1314
private readonly TableClient _snapshotTableClient;
1415
private readonly Dictionary<string, DatapointMapping> _datapointMappings;
@@ -20,9 +21,10 @@ public class BuderusSinkAzTablesService : IEventSink<BuderusEvent>, IBuderusQuer
2021
/// Initializes a new instance of the <see cref="BuderusSinkAzTablesService"/> class.
2122
/// </summary>
2223
public BuderusSinkAzTablesService(ILogger<BuderusSinkAzTablesService> logger, IOptions<BuderusConfig> config,
23-
IOptions<AzureAuthConfig> azureAuthConfig)
24+
IOptions<AzureAuthConfig> azureAuthConfig, TimeProvider timeProvider)
2425
{
2526
_logger = logger;
27+
_timeProvider = timeProvider;
2628

2729
var azConfig = config.Value.Sinks.AvailableSinks["AzureTables"];
2830
var connectionString = config.Value.AzureTableStorageConnectionString;
@@ -69,7 +71,7 @@ public async Task WriteEvent(BuderusEvent @event, CancellationToken cancellation
6971
/// <inheritdoc/>
7072
public async IAsyncEnumerable<BuderusEvent> GetEvents(string? id = null, int limit = 1000, [EnumeratorCancellation] CancellationToken cancellationToken = default)
7173
{
72-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
74+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
7375
AsyncPageable<BuderusReadingEntity> entities;
7476
if (id is null)
7577
entities = _lineItemTableClient.QueryAsync<BuderusReadingEntity>(ent => ent.PartitionKey == partitionKey, cancellationToken: cancellationToken);

src/CasCap.Api.Buderus.Sinks/Services/Sinks/BuderusSinkRedisService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace CasCap.Services;
88
public class BuderusSinkRedisService(
99
ILogger<BuderusSinkRedisService> logger,
1010
IOptions<BuderusConfig> buderusConfig,
11+
TimeProvider timeProvider,
1112
IRemoteCache remoteCache
1213
) : IEventSink<BuderusEvent>, IBuderusQuery
1314
{
@@ -63,13 +64,13 @@ public async IAsyncEnumerable<BuderusEvent> GetEvents(string? id = null, int lim
6364
// Snapshot: yield every hash entry as an event
6465
var entries = await remoteCache.Db.HashGetAllAsync(_summaryValues);
6566
foreach (var entry in entries)
66-
yield return new BuderusEvent(entry.Name.ToString(), entry.Value.ToString(), DateTime.UtcNow);
67+
yield return new BuderusEvent(entry.Name.ToString(), entry.Value.ToString(), timeProvider.GetUtcNow().UtcDateTime);
6768
}
6869
else
6970
{
7071
// Line items: controller passes underscore-separated partition key format; normalize to slash format for Redis key lookup
7172
var datapointId = id.Replace('_', '/');
72-
var lineItemKey = $"{_seriesValues}:{DateTime.UtcNow:yyMMdd}:{datapointId}";
73+
var lineItemKey = $"{_seriesValues}:{timeProvider.GetUtcNow().UtcDateTime:yyMMdd}:{datapointId}";
7374
var entries = await remoteCache.Db.SortedSetRangeByScoreWithScoresAsync(lineItemKey, order: Order.Descending, take: Math.Min(limit, 1000));
7475
foreach (var entry in entries)
7576
yield return new BuderusEvent(id, entry.Element!, new DateTime((long)entry.Score, DateTimeKind.Utc));

src/CasCap.Api.Buderus/Services/Sinks/BuderusSinkMemoryService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace CasCap.Services;
55
/// and provides snapshot queries without requiring external infrastructure.
66
/// </summary>
77
[SinkType("Memory")]
8-
public class BuderusSinkMemoryService(ILogger<BuderusSinkMemoryService> logger, IOptions<BuderusConfig> config) : IEventSink<BuderusEvent>, IBuderusQuery
8+
public class BuderusSinkMemoryService(ILogger<BuderusSinkMemoryService> logger, IOptions<BuderusConfig> config, TimeProvider timeProvider) : IEventSink<BuderusEvent>, IBuderusQuery
99
{
1010
private readonly ConcurrentDictionary<string, string> _values = new();
1111

@@ -37,7 +37,7 @@ public async IAsyncEnumerable<BuderusEvent> GetEvents(string? id = null, int lim
3737
if (id is null)
3838
{
3939
foreach (var (key, value) in _values)
40-
yield return new BuderusEvent(key, value, DateTime.UtcNow);
40+
yield return new BuderusEvent(key, value, timeProvider.GetUtcNow().UtcDateTime);
4141
}
4242
}
4343
}

src/CasCap.Api.DoorBird.Sinks/Services/Sinks/DoorBirdSinkAzTablesService.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace CasCap.Services;
1010
public class DoorBirdSinkAzTablesService : IEventSink<DoorBirdEvent>, IDoorBirdQuery
1111
{
1212
private readonly ILogger _logger;
13+
private readonly TimeProvider _timeProvider;
1314
private readonly TableClient _lineItemTableClient;
1415
private readonly TableClient _snapshotTableClient;
1516

@@ -28,9 +29,11 @@ public class DoorBirdSinkAzTablesService : IEventSink<DoorBirdEvent>, IDoorBirdQ
2829
/// </summary>
2930
public DoorBirdSinkAzTablesService(ILogger<DoorBirdSinkAzTablesService> logger,
3031
IOptions<AzureAuthConfig> azureAuthConfig,
31-
IOptions<DoorBirdConfig> config)
32+
IOptions<DoorBirdConfig> config,
33+
TimeProvider timeProvider)
3234
{
3335
_logger = logger;
36+
_timeProvider = timeProvider;
3437

3538
var azConfig = config.Value.Sinks.AvailableSinks["AzureTables"];
3639
var connectionString = config.Value.AzureTableStorageConnectionString;
@@ -72,7 +75,7 @@ public async Task WriteEvent(DoorBirdEvent @event, CancellationToken cancellatio
7275
public async IAsyncEnumerable<DoorBirdEvent> GetEvents(string? id = null, int limit = 1000,
7376
[EnumeratorCancellation] CancellationToken cancellationToken = default)
7477
{
75-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
78+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
7679
AsyncPageable<DoorBirdReadingEntity> entities;
7780
if (id is null)
7881
entities = _lineItemTableClient.QueryAsync<DoorBirdReadingEntity>(ent => ent.PartitionKey == partitionKey, cancellationToken: cancellationToken);
@@ -98,7 +101,7 @@ public async Task<DoorBirdSnapshot> GetSnapshot()
98101
var entity = await GetSnapshotEntity();
99102
return new DoorBirdSnapshot
100103
{
101-
SnapshotUtc = DateTime.UtcNow,
104+
SnapshotUtc = _timeProvider.GetUtcNow().UtcDateTime,
102105
LastDoorbellUtc = entity.LastDoorbellUtc?.UtcDateTime,
103106
LastMotionUtc = entity.LastMotionUtc?.UtcDateTime,
104107
LastRfidUtc = entity.LastRfidUtc?.UtcDateTime,
@@ -127,7 +130,7 @@ internal async Task<DoorBirdSnapshotEntity> GetSnapshotEntity(CancellationToken
127130
/// <param name="limit">Maximum number of records to return. Default 100, maximum 1000.</param>
128131
public async Task<IEnumerable<DoorBirdReadingEntity>> GetReadings(int limit = 100)
129132
{
130-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
133+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
131134
_logger.LogInformation("{ClassName} Getting data from table storage for partitionKey {PartitionKey}",
132135
nameof(DoorBirdSinkAzTablesService), partitionKey);
133136
var entities = await _lineItemTableClient.QueryAsync<DoorBirdReadingEntity>(

src/CasCap.Api.DoorBird.Sinks/Services/Sinks/DoorBirdSinkRedisService.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace CasCap.Services;
1313
public class DoorBirdSinkRedisService(
1414
ILogger<DoorBirdSinkRedisService> logger,
1515
IOptions<DoorBirdConfig> doorBirdConfig,
16+
TimeProvider timeProvider,
1617
IRemoteCache remoteCache
1718
) : IEventSink<DoorBirdEvent>, IDoorBirdQuery
1819
{
@@ -64,14 +65,14 @@ public async Task WriteEvent(DoorBirdEvent @event, CancellationToken cancellatio
6465
public async Task<DoorBirdSnapshot> GetSnapshot()
6566
{
6667
if (string.IsNullOrWhiteSpace(_summaryValues))
67-
return new() { SnapshotUtc = DateTime.UtcNow };
68+
return new() { SnapshotUtc = timeProvider.GetUtcNow().UtcDateTime };
6869

6970
var entries = await remoteCache.Db.HashGetAllAsync(_summaryValues);
7071
var dict = entries.ToDictionary(e => e.Name.ToString(), e => e.Value.ToString());
7172

7273
return new DoorBirdSnapshot
7374
{
74-
SnapshotUtc = DateTime.UtcNow,
75+
SnapshotUtc = timeProvider.GetUtcNow().UtcDateTime,
7576
LastDoorbellUtc = TryGetDateTimeFromTicks(dict, nameof(DoorBirdSnapshotEntity.LastDoorbellUtc)),
7677
LastMotionUtc = TryGetDateTimeFromTicks(dict, nameof(DoorBirdSnapshotEntity.LastMotionUtc)),
7778
LastRfidUtc = TryGetDateTimeFromTicks(dict, nameof(DoorBirdSnapshotEntity.LastRfidUtc)),
@@ -94,7 +95,7 @@ public async IAsyncEnumerable<DoorBirdEvent> GetEvents(string? id = null, int li
9495
// Yield today's events across all event types
9596
foreach (var eventType in Enum.GetValues<DoorBirdEventType>())
9697
{
97-
var lineItemKey = $"{_seriesValues}:{DateTime.UtcNow:yyMMdd}:{eventType}";
98+
var lineItemKey = $"{_seriesValues}:{timeProvider.GetUtcNow().UtcDateTime:yyMMdd}:{eventType}";
9899
var entries = await remoteCache.Db.SortedSetRangeByScoreWithScoresAsync(lineItemKey, order: Order.Descending, take: Math.Min(limit, 1000));
99100
foreach (var entry in entries)
100101
yield return new DoorBirdEvent
@@ -106,7 +107,7 @@ public async IAsyncEnumerable<DoorBirdEvent> GetEvents(string? id = null, int li
106107
}
107108
else if (Enum.TryParse<DoorBirdEventType>(id, ignoreCase: true, out var parsedType))
108109
{
109-
var lineItemKey = $"{_seriesValues}:{DateTime.UtcNow:yyMMdd}:{parsedType}";
110+
var lineItemKey = $"{_seriesValues}:{timeProvider.GetUtcNow().UtcDateTime:yyMMdd}:{parsedType}";
110111
var entries = await remoteCache.Db.SortedSetRangeByScoreWithScoresAsync(lineItemKey, order: Order.Descending, take: Math.Min(limit, 1000));
111112
foreach (var entry in entries)
112113
yield return new DoorBirdEvent

src/CasCap.Api.DoorBird/Services/Sinks/DoorBirdSinkMemoryService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace CasCap.Services;
55
/// per <see cref="DoorBirdEventType"/> and provides snapshot queries without requiring external infrastructure.
66
/// </summary>
77
[SinkType("Memory")]
8-
public class DoorBirdSinkMemoryService(ILogger<DoorBirdSinkMemoryService> logger) : IEventSink<DoorBirdEvent>, IDoorBirdQuery
8+
public class DoorBirdSinkMemoryService(ILogger<DoorBirdSinkMemoryService> logger, TimeProvider timeProvider) : IEventSink<DoorBirdEvent>, IDoorBirdQuery
99
{
1010
private readonly ConcurrentDictionary<DoorBirdEventType, (DateTime LastUtc, int Count)> _state = new();
1111

@@ -24,7 +24,7 @@ public Task WriteEvent(DoorBirdEvent @event, CancellationToken cancellationToken
2424
public Task<DoorBirdSnapshot> GetSnapshot()
2525
=> Task.FromResult(new DoorBirdSnapshot
2626
{
27-
SnapshotUtc = DateTime.UtcNow,
27+
SnapshotUtc = timeProvider.GetUtcNow().UtcDateTime,
2828
LastDoorbellUtc = GetLastUtc(DoorBirdEventType.Doorbell),
2929
LastMotionUtc = GetLastUtc(DoorBirdEventType.MotionSensor),
3030
LastRfidUtc = GetLastUtc(DoorBirdEventType.Rfid),

src/CasCap.Api.EdgeHardware.Sinks/Services/Sinks/EdgeHardwareSinkAzTablesService.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace CasCap.Services;
88
public class EdgeHardwareSinkAzTablesService : IEventSink<EdgeHardwareEvent>, IEdgeHardwareQuery
99
{
1010
private readonly ILogger _logger;
11+
private readonly TimeProvider _timeProvider;
1112
private readonly TableClient _lineItemTableClient;
1213
private readonly TableClient _snapshotTableClient;
1314

@@ -18,9 +19,11 @@ public class EdgeHardwareSinkAzTablesService : IEventSink<EdgeHardwareEvent>, IE
1819
/// </summary>
1920
public EdgeHardwareSinkAzTablesService(ILogger<EdgeHardwareSinkAzTablesService> logger,
2021
IOptions<AzureAuthConfig> azureAuthConfig,
21-
IOptions<EdgeHardwareConfig> config)
22+
IOptions<EdgeHardwareConfig> config,
23+
TimeProvider timeProvider)
2224
{
2325
_logger = logger;
26+
_timeProvider = timeProvider;
2427

2528
var azConfig = config.Value.Sinks.AvailableSinks["AzureTables"];
2629
var connectionString = config.Value.AzureTableStorageConnectionString;
@@ -82,7 +85,7 @@ public async Task<List<EdgeHardwareSnapshot>> GetSnapshots()
8285
public async IAsyncEnumerable<EdgeHardwareEvent> GetEvents(string? id = null, int limit = 1000,
8386
[EnumeratorCancellation] CancellationToken cancellationToken = default)
8487
{
85-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
88+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
8689
_logger.LogInformation("{ClassName} getting data from table storage for partitionKey {PartitionKey}",
8790
nameof(EdgeHardwareSinkAzTablesService), partitionKey);
8891

src/CasCap.Api.EdgeHardware.Sinks/Services/Sinks/EdgeHardwareSinkRedisService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace CasCap.Services;
99
public class EdgeHardwareSinkRedisService(
1010
ILogger<EdgeHardwareSinkRedisService> logger,
1111
IOptions<EdgeHardwareConfig> edgeHardwareConfig,
12+
TimeProvider timeProvider,
1213
IRemoteCache remoteCache
1314
) : IEventSink<EdgeHardwareEvent>, IEdgeHardwareQuery
1415
{
@@ -94,7 +95,7 @@ public async IAsyncEnumerable<EdgeHardwareEvent> GetEvents(string? id = null, in
9495
if (string.IsNullOrWhiteSpace(_snapshotValues))
9596
yield break;
9697

97-
var lineItemKey = $"{_seriesValues}:{DateTime.UtcNow:yyMMdd}";
98+
var lineItemKey = $"{_seriesValues}:{timeProvider.GetUtcNow().UtcDateTime:yyMMdd}";
9899
var entries = await remoteCache.Db.SortedSetRangeByScoreWithScoresAsync(lineItemKey, order: Order.Descending, take: Math.Min(limit, 1000));
99100

100101
foreach (var entry in entries)

src/CasCap.Api.Fronius.Sinks/Services/Sinks/FroniusSinkAzTablesService.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace CasCap.Services;
88
public class FroniusSinkAzTablesService : IEventSink<FroniusEvent>, IFroniusQuery
99
{
1010
private readonly ILogger _logger;
11+
private readonly TimeProvider _timeProvider;
1112
private readonly TableClient _lineItemTableClient;
1213
private readonly TableClient _snapshotTableClient;
1314

@@ -19,9 +20,11 @@ public class FroniusSinkAzTablesService : IEventSink<FroniusEvent>, IFroniusQuer
1920
/// </summary>
2021
public FroniusSinkAzTablesService(ILogger<FroniusSinkAzTablesService> logger,
2122
IOptions<AzureAuthConfig> azureAuthConfig,
22-
IOptions<FroniusConfig> config)
23+
IOptions<FroniusConfig> config,
24+
TimeProvider timeProvider)
2325
{
2426
_logger = logger;
27+
_timeProvider = timeProvider;
2528

2629
var azConfig = config.Value.Sinks.AvailableSinks["AzureTables"];
2730
var connectionString = config.Value.AzureTableStorageConnectionString;
@@ -58,7 +61,7 @@ public async Task WriteEvent(FroniusEvent @event, CancellationToken cancellation
5861
public async IAsyncEnumerable<FroniusEvent> GetEvents(string? id = null, int limit = 1000,
5962
[EnumeratorCancellation] CancellationToken cancellationToken = default)
6063
{
61-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
64+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
6265
var entities = _lineItemTableClient.QueryAsync<FroniusReadingEntity>(
6366
ent => ent.PartitionKey == partitionKey, cancellationToken: cancellationToken);
6467

@@ -101,7 +104,7 @@ internal async Task<FroniusSnapshotEntity> GetSnapshotEntity()
101104
/// <param name="limit">Maximum number of records to return. Default 100, maximum 1000.</param>
102105
public async Task<IEnumerable<FroniusReadingEntity>> GetReadings(int limit = 100)
103106
{
104-
var partitionKey = DateTime.UtcNow.ToString("yyMMdd");
107+
var partitionKey = _timeProvider.GetUtcNow().UtcDateTime.ToString("yyMMdd");
105108
_logger.LogInformation("{ClassName} Getting data from table storage for partitionKey '{PartitionKey}'",
106109
nameof(FroniusSinkAzTablesService), partitionKey);
107110
var entities = await _lineItemTableClient.QueryAsync<FroniusReadingEntity>(

src/CasCap.Api.Fronius.Sinks/Services/Sinks/FroniusSinkRedisService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace CasCap.Services;
1010
public class FroniusSinkRedisService(
1111
ILogger<FroniusSinkRedisService> logger,
1212
IOptions<FroniusConfig> froniusConfig,
13+
TimeProvider timeProvider,
1314
IRemoteCache remoteCache
1415
) : IEventSink<FroniusEvent>, IFroniusQuery
1516
{
@@ -74,7 +75,7 @@ public async IAsyncEnumerable<FroniusEvent> GetEvents(string? id = null, int lim
7475
if (string.IsNullOrWhiteSpace(_summaryValues))
7576
yield break;
7677

77-
var lineItemKey = $"{_seriesValues}:{DateTime.UtcNow:yyMMdd}";
78+
var lineItemKey = $"{_seriesValues}:{timeProvider.GetUtcNow().UtcDateTime:yyMMdd}";
7879
var entries = await remoteCache.Db.SortedSetRangeByScoreWithScoresAsync(lineItemKey, order: Order.Descending, take: Math.Min(limit, 1000));
7980

8081
foreach (var entry in entries)

0 commit comments

Comments
 (0)