Skip to content

Commit 1f20096

Browse files
authored
Merge pull request #24 from f2calv/f2calv/2026-05-updates3
feat: auto-derive Redis consumer names from pod identity & replace polling with TaskCompletionSource
2 parents 5ad755e + 8ae6f9a commit 1f20096

9 files changed

Lines changed: 40 additions & 54 deletions

File tree

Directory.Packages.props

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,46 @@
1515
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
1616
<PackageVersion Include="Azure.Identity" Version="1.21.0" />
1717
<PackageVersion Include="Azure.ResourceManager.Dns" Version="1.1.1" />
18-
<PackageVersion Include="CasCap.Api.Azure.Auth" Version="1.4.7" />
19-
<PackageVersion Include="CasCap.Api.Azure.Storage" Version="1.4.7" />
18+
<PackageVersion Include="CasCap.Api.Azure.Auth" Version="1.4.8" />
19+
<PackageVersion Include="CasCap.Api.Azure.Storage" Version="1.4.8" />
2020
<PackageVersion Include="CasCap.Common.Abstractions" Version="4.10.1" />
21-
<PackageVersion Include="CasCap.Common.AI" Version="4.11.2" />
22-
<PackageVersion Include="CasCap.Common.Caching" Version="4.11.2" />
23-
<PackageVersion Include="CasCap.Common.Configuration" Version="4.11.2" />
24-
<PackageVersion Include="CasCap.Common.Extensions" Version="4.11.2" />
25-
<PackageVersion Include="CasCap.Common.Extensions.Diagnostics.HealthChecks" Version="4.11.2" />
26-
<PackageVersion Include="CasCap.Common.Logging" Version="4.11.2" />
27-
<PackageVersion Include="CasCap.Common.Logging.Serilog" Version="4.11.2" />
28-
<PackageVersion Include="CasCap.Common.Net" Version="4.11.2" />
29-
<PackageVersion Include="CasCap.Common.OpenTelemetry" Version="4.11.2" />
30-
<PackageVersion Include="CasCap.Common.Serialization.Json" Version="4.11.2" />
31-
<PackageVersion Include="CasCap.Common.Serialization.MessagePack" Version="4.11.2" />
32-
<PackageVersion Include="CasCap.Common.Services" Version="4.11.2" />
33-
<PackageVersion Include="CasCap.Common.Testing" Version="4.11.2" />
21+
<PackageVersion Include="CasCap.Common.AI" Version="4.11.3" />
22+
<PackageVersion Include="CasCap.Common.Caching" Version="4.11.3" />
23+
<PackageVersion Include="CasCap.Common.Configuration" Version="4.11.3" />
24+
<PackageVersion Include="CasCap.Common.Extensions" Version="4.11.3" />
25+
<PackageVersion Include="CasCap.Common.Extensions.Diagnostics.HealthChecks" Version="4.11.3" />
26+
<PackageVersion Include="CasCap.Common.Logging" Version="4.11.3" />
27+
<PackageVersion Include="CasCap.Common.Logging.Serilog" Version="4.11.3" />
28+
<PackageVersion Include="CasCap.Common.Net" Version="4.11.3" />
29+
<PackageVersion Include="CasCap.Common.OpenTelemetry" Version="4.11.3" />
30+
<PackageVersion Include="CasCap.Common.Serialization.Json" Version="4.11.3" />
31+
<PackageVersion Include="CasCap.Common.Serialization.MessagePack" Version="4.11.3" />
32+
<PackageVersion Include="CasCap.Common.Services" Version="4.11.3" />
33+
<PackageVersion Include="CasCap.Common.Testing" Version="4.11.3" />
3434
<PackageVersion Include="ILGPU" Version="1.5.3" />
3535
<PackageVersion Include="Iot.Device.Bindings" Version="4.2.0" />
3636
<PackageVersion Include="LibreHardwareMonitorLib" Version="0.9.6" />
3737
<PackageVersion Include="Knx.Falcon.Sdk" Version="6.4.8671" />
3838
<PackageVersion Include="KoenZomers.UniFi.Api" Version="2.3.1" />
3939
<PackageVersion Include="Microsoft.Agents.AI" Version="1.2.0" />
40-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.9" />
40+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.10" />
4141
<PackageVersion Include="Microsoft.Extensions.AI" Version="10.5.0" />
4242
<PackageVersion Include="Microsoft.Extensions.AI.Abstractions" Version="10.5.0" />
4343
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.5.0" />
44-
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.7" />
45-
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="10.0.7" />
46-
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
44+
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.8" />
45+
<PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="10.0.8" />
46+
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.8" />
4747
<PackageVersion Include="Microsoft.ML.Tokenizers.Data.Cl100kBase" Version="2.0.0" />
4848
<PackageVersion Include="MMALSharp" Version="0.6.0" />
4949
<PackageVersion Include="MMALSharp.FFmpeg" Version="0.6.0" />
50-
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.9" />
51-
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.7" />
52-
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="10.0.7" />
53-
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="10.0.7" />
54-
<PackageVersion Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="10.0.7" />
55-
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.7" />
56-
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.5.0" />
57-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.7" />
50+
<PackageVersion Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.10" />
51+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.8" />
52+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="10.0.8" />
53+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="10.0.8" />
54+
<PackageVersion Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="10.0.8" />
55+
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.8" />
56+
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="10.6.0" />
57+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.8" />
5858
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
5959
<!--<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />-->
6060
<PackageVersion Include="ModelContextProtocol" Version="1.2.0" />

SmartHaus.Debug.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<Project Path="../CasCap.Common/src/CasCap.Common.Logging/CasCap.Common.Logging.csproj" />
3535
<Project Path="../CasCap.Common/src/CasCap.Common.Net.Tests/CasCap.Common.Net.Tests.csproj" />
3636
<Project Path="../CasCap.Common/src/CasCap.Common.Net/CasCap.Common.Net.csproj" />
37+
<Project Path="../CasCap.Common/src/CasCap.Common.OpenTelemetry/CasCap.Common.OpenTelemetry.csproj" />
3738
<Project Path="../CasCap.Common/src/CasCap.Common.Serialization.Json/CasCap.Common.Serialization.Json.csproj" />
3839
<Project Path="../CasCap.Common/src/CasCap.Common.Serialization.MessagePack/CasCap.Common.Serialization.MessagePack.csproj" />
3940
<Project Path="../CasCap.Common/src/CasCap.Common.Serialization.Tests/CasCap.Common.Serialization.Tests.csproj" />

src/CasCap.Api.Knx.Sinks/Services/Sinks/KnxSinkStateChange.cs

Whitespace-only changes.

src/CasCap.Api.Knx/Services/RedisKnxTelegramBroker{T}.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ public class RedisKnxTelegramBroker<T>(
2424
int streamExpiryDays
2525
) : IKnxTelegramBroker<T> where T : class
2626
{
27-
private const int MaxConsumerNameLength = 24;
28-
2927
private readonly IDatabase _db = remoteCache.Db;
30-
private readonly string _consumerName = $"{Environment.MachineName}-{Guid.NewGuid():N}"[..MaxConsumerNameLength];
28+
private readonly string _consumerName = $"{Environment.MachineName}-{AppDomain.CurrentDomain.FriendlyName}";
3129

3230
// Track which date-partitioned stream keys have had their consumer group created
3331
private readonly HashSet<string> _groupCreatedKeys = [];

src/CasCap.SmartHaus/Models/_CommsAgentConfig.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ public record CommsAgentConfig : IAppConfig
6060
public string ConsumerGroup { get; init; } = "comms:agents";
6161

6262
/// <summary>Consumer name identifying this instance within the consumer group.</summary>
63-
/// <remarks>Defaults to <c>"comms-0"</c>. Used by <see cref="CasCap.Services.CommunicationsBgService"/>.</remarks>
63+
/// <remarks>Defaults to <c>{MachineName}-{AppName}</c> for automatic per-pod uniqueness in Kubernetes.</remarks>
6464
[Required, MinLength(1)]
65-
public string ConsumerName { get; init; } = "comms-0";
65+
public string ConsumerName { get; init; } = $"{Environment.MachineName}-{AppDomain.CurrentDomain.FriendlyName}";
6666

6767
/// <summary>Starting ID used when creating the consumer group for the first time.</summary>
6868
/// <remarks>Defaults to <c>"0"</c> (read from the beginning). Used by <see cref="CasCap.Services.CommunicationsBgService"/>.</remarks>
@@ -109,15 +109,4 @@ public record CommsAgentConfig : IAppConfig
109109
/// </remarks>
110110
[Range(1, int.MaxValue)]
111111
public int FlushTimeoutMs { get; init; } = 5_000;
112-
113-
/// <summary>
114-
/// Delay in milliseconds between polls when waiting for the Signal group to be resolved
115-
/// before delivering a stream event.
116-
/// </summary>
117-
/// <remarks>
118-
/// Defaults to <c>1000</c> ms (1 second).
119-
/// Used by <see cref="CasCap.Services.CommunicationsBgService"/>.
120-
/// </remarks>
121-
[Range(1, int.MaxValue)]
122-
public int GroupResolutionPollingDelayMs { get; init; } = 1_000;
123112
}

src/CasCap.SmartHaus/Models/_MediaConfig.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ public record MediaConfig : IAppConfig
2929
public string ConsumerGroup { get; init; } = "media:processors";
3030

3131
/// <summary>Consumer name identifying this instance within the consumer group.</summary>
32-
/// <remarks>Defaults to <c>"media-0"</c>. Used by <see cref="CasCap.Services.MediaBgService"/>.</remarks>
32+
/// <remarks>Defaults to <c>{MachineName}-{AppName}</c> for automatic per-pod uniqueness in Kubernetes.</remarks>
3333
[Required, MinLength(1)]
34-
public string ConsumerName { get; init; } = "media-0";
34+
public string ConsumerName { get; init; } = $"{Environment.MachineName}-{AppDomain.CurrentDomain.FriendlyName}";
3535

3636
/// <summary>Starting ID used when creating the consumer group for the first time.</summary>
3737
/// <remarks>Defaults to <c>"0"</c> (read from the beginning). Used by <see cref="CasCap.Services.MediaBgService"/>.</remarks>

src/CasCap.SmartHaus/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ These sinks are registered in the feature pods and forward domain events to the
8181
| `PollingIntervalMs` | `int` | `5000` | Polling interval for comms stream and REST message retrieval |
8282
| `HealthCheckProbeDelayMs` | `int` | `2000` | Delay in milliseconds between signal-cli readiness probes at startup |
8383
| `FlushTimeoutMs` | `int` | `5000` | Timeout in milliseconds for flushing pending envelopes at startup |
84-
| `GroupResolutionPollingDelayMs` | `int` | `1000` | Delay in milliseconds between polls when waiting for Signal group resolution |
8584

8685
### `MediaConfig` (`CasCap:MediaConfig`)
8786

src/CasCap.SmartHaus/Services/CommunicationsBgService.Stream.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,7 @@ private async Task ProcessCommsEventAsync(CommsEvent commsEvent, CancellationTok
7777
await _debugNotifier.SendStreamEventDebugAsync(commsEvent, cancellationToken);
7878

7979
// Wait until Signal group resolution completes before attempting delivery.
80-
if (_groupId is null)
81-
{
82-
_logger.LogInformation("{ClassName} Signal group not yet resolved, waiting before delivering stream event",
83-
nameof(CommunicationsBgService));
84-
while (_groupId is null && !cancellationToken.IsCancellationRequested)
85-
await Task.Delay(_commsAgentConfig.GroupResolutionPollingDelayMs, cancellationToken);
86-
}
80+
await _groupResolved.Task.WaitAsync(cancellationToken);
8781

8882
if (_agent is null || _commsAgent is null || _provider is null)
8983
{

src/CasCap.SmartHaus/Services/CommunicationsBgService.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public partial class CommunicationsBgService : IBgFeature
5252
private readonly AgentConfig? _audioAgentConfig;
5353

5454
private string? _groupId;
55+
private readonly TaskCompletionSource _groupResolved = new(TaskCreationOptions.RunContinuationsAsynchronously);
5556
private readonly string? _resolvedInstructions;
5657
private readonly ConcurrentQueue<ReplyRequest> _replyQueue = new();
5758
private readonly SemaphoreSlim _replySignal = new(0);
@@ -181,7 +182,9 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
181182
try
182183
{
183184
groups = await _notifier.ListGroupsAsync(_signalCliConfig.PhoneNumber, cancellationToken);
184-
_logger.LogInformation("{ClassName} found {GroupCount} group(s)", nameof(CommunicationsBgService), groups?.Length ?? 0);
185+
_logger.LogInformation("{ClassName} found {GroupCount} group(s): {GroupNames}",
186+
nameof(CommunicationsBgService), groups?.Length ?? 0,
187+
groups is not null ? string.Join(", ", groups.Select(g => g.Name)) : "(none)");
185188
}
186189
catch (Exception ex) when (ex is not OperationCanceledException and not TaskCanceledException)
187190
{
@@ -208,6 +211,8 @@ public async Task ExecuteAsync(CancellationToken cancellationToken)
208211
$"group '{_commsAgentConfig.GroupName}' not found among [{(groups is not null ? string.Join(", ", groups.Select(g => g.Name)) : "(none)")}] and no GroupId fallback configured");
209212
}
210213

214+
_groupResolved.TrySetResult();
215+
211216
_logger.LogInformation("{ClassName} starting background tasks (notifier={NotifierType})",
212217
nameof(CommunicationsBgService), _notifier.GetType().Name);
213218

0 commit comments

Comments
 (0)