From f86b78593e57b5b6419feb4c32525827d994300f Mon Sep 17 00:00:00 2001 From: Mika Kuns Date: Tue, 23 Jun 2026 16:02:29 +0200 Subject: [PATCH] fix(online): honor runtime disable in sync loop to stop OIDC discovery OnlineSyncService is registered once at startup; toggling the feature off in Settings persisted the flag but never stopped the running loop, so it kept polling and failing OIDC discovery every cycle. Guard TickAsync on the shared config's Enabled flag so disabling takes effect live. --- src/ClaudeDo.Worker/Online/OnlineSyncService.cs | 6 ++++++ .../Online/OnlineSyncServiceTests.cs | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/ClaudeDo.Worker/Online/OnlineSyncService.cs b/src/ClaudeDo.Worker/Online/OnlineSyncService.cs index 091765a..3afb1e5 100644 --- a/src/ClaudeDo.Worker/Online/OnlineSyncService.cs +++ b/src/ClaudeDo.Worker/Online/OnlineSyncService.cs @@ -66,6 +66,12 @@ public sealed class OnlineSyncService : BackgroundService internal async Task TickAsync(CancellationToken ct) { + // Respect a runtime disable. The hosted service stays registered for the process + // lifetime, so toggling the feature off in Settings must stop all sync + auth work + // (incl. OIDC discovery) here — otherwise the loop keeps polling until a restart. + if (!_config.Enabled) + return; + var token = await _auth.GetAccessTokenAsync(ct); if (token is null) { diff --git a/tests/ClaudeDo.Worker.Tests/Online/OnlineSyncServiceTests.cs b/tests/ClaudeDo.Worker.Tests/Online/OnlineSyncServiceTests.cs index 15288d6..1edbe5c 100644 --- a/tests/ClaudeDo.Worker.Tests/Online/OnlineSyncServiceTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Online/OnlineSyncServiceTests.cs @@ -55,9 +55,9 @@ public sealed class OnlineSyncServiceTests : IDisposable } } - private OnlineSyncService BuildService(FakeApi api, string? token = "test-token") + private OnlineSyncService BuildService(FakeApi api, string? token = "test-token", bool enabled = true) { - var config = new OnlineInboxConfig { Enabled = true, PollIntervalSeconds = 60 }; + var config = new OnlineInboxConfig { Enabled = enabled, PollIntervalSeconds = 60 }; var auth = new StaticTokenAuthProvider(token); return new OnlineSyncService( _db.CreateFactory(), @@ -209,6 +209,18 @@ public sealed class OnlineSyncServiceTests : IDisposable Assert.Equal(0, api.CallCount); } + [Fact] + public async Task Tick_Disabled_SkipsCycle_NoApiCalls() + { + _ = await SeedAsync(); + var api = new FakeApi(); + var svc = BuildService(api, enabled: false); + + await svc.TickAsync(CancellationToken.None); + + Assert.Equal(0, api.CallCount); + } + // ---- multi-user: owner stamping + guard ---- [Fact]