Upgrade to .NET 10 - #18
Conversation
Retarget all projects from net8.0 to net10.0 and move dependencies to the 10.0.x band. - global.json: pin the SDK to 10.0.100 (rollForward: latestMinor) - All six projects: net8.0 -> net10.0 - Microsoft.Extensions.* and EntityFrameworkCore.Relational: 8.0.x -> 10.0.10 - Test stack: Test.Sdk 18.8.1, xunit 2.9.3, xunit.runner.visualstudio 3.1.5, coverlet.collector 10.0.1 - Nerdbank.GitVersioning: 3.7.115 -> 3.10.91 for SDK 10 compatibility - CI: actions/setup-dotnet 8.0.x -> 10.0.x Verified with clean Debug and Release builds (0 warnings), 92/92 tests passing in both configurations, dotnet pack producing all three packages, and both example projects running correctly. Note: this drops support for consumers targeting .NET 8 and 9, since the published packages no longer target net8.0. Happy to multi-target net8.0;net10.0 instead if that is preferred. Fixes feature23#17 Co-Authored-By: Claude
|
Retargets all projects from Changes
No source files changed — this is entirely build configuration. Verification
One call I'd like your input on: this breaks .NET 8/9 consumersThe published packages no longer target Verified against a clean I went with a straight retarget on the assumption that pre-1.0 ( |
|
Title: Skipped eligibility checks reset the interval clock, so entities stop syncing after the first run SummaryWhen the host polls more frequently than the configured eligibility interval, an entity syncs This is triggered by the configuration the README recommends — "the frequency of these checks Reproduction
Minimal executable repro — fails on public class IntervalSkipReproTests
{
private class ReproEntity;
private class CountingSync : IEntitySync
{
public static int RunCount;
public Task<SyncResult> Run(EntitySyncContext context, CancellationToken cancellationToken = default)
{
Interlocked.Increment(ref RunCount);
return Task.FromResult(new SyncResult(context.Entity, Success: true));
}
}
[Fact]
public async Task SkippedChecks_ShouldNotResetTheIntervalClock()
{
CountingSync.RunCount = 0;
var services = new ServiceCollection();
services.AddLogging();
services.AddSyncerbell(options =>
{
options.AddEntity<ReproEntity, CountingSync>(entity =>
entity.Eligibility = new IntervalEligibilityStrategy(TimeSpan.FromMilliseconds(500)));
})
.AddSyncerbellInMemoryPersistence();
var syncService = services.BuildServiceProvider().GetRequiredService<ISyncService>();
// t=0: no prior sync, so this should run.
await syncService.SyncAllEligible(SyncTriggerType.Timer);
Assert.Equal(1, CountingSync.RunCount);
// t=300ms: only 300ms since the last sync, so skipping is correct.
await Task.Delay(300);
await syncService.SyncAllEligible(SyncTriggerType.Timer);
Assert.Equal(1, CountingSync.RunCount);
// t=600ms: 600ms since the last actual sync exceeds the 500ms interval,
// so this should run again.
await Task.Delay(300);
await syncService.SyncAllEligible(SyncTriggerType.Timer);
Assert.Equal(2, CountingSync.RunCount);
}
}Expected: the entity syncs again once the interval has elapsed since the last actual sync. Root causeEach ineligible check still creates and leases a log entry, and that entry then feeds the next
With poll period < interval, elapsed never reaches the interval and the entity is permanently Both persistence implementations are affected:
Secondary concernEvery skipped poll also writes a row. At a 30-second poll interval that is ~2,880 Possible fixes
Happy to open a PR for either — just let me know which direction you'd prefer. NotesVerified against |
Retarget all projects from net8.0 to net10.0 and move dependencies to the 10.0.x band.
Verified with clean Debug and Release builds (0 warnings), 92/92 tests passing in both configurations, dotnet pack producing all three packages, and both example projects running correctly.
Note: this drops support for consumers targeting .NET 8 and 9, since the published packages no longer target net8.0. Happy to multi-target net8.0;net10.0 instead if that is preferred.
Fixes #17
Co-Authored-By: Claude