test(galaxyrepo): projector + cache tests; dispose semaphores; pack 0.1.0

This commit is contained in:
Joseph Doherty
2026-06-23 20:34:32 -04:00
parent a30f8551e9
commit 2c6c764d3c
7 changed files with 935 additions and 4 deletions
@@ -14,7 +14,7 @@ namespace ZB.MOM.WW.GalaxyRepository;
/// snapshot (as <see cref="GalaxyCacheStatus.Stale"/>) so clients can browse
/// last-known data when the Galaxy database is unreachable on a cold start.
/// </summary>
public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache
public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache, IDisposable
{
private static readonly TimeSpan StaleThreshold = TimeSpan.FromMinutes(5);
@@ -88,6 +88,16 @@ public sealed class GalaxyHierarchyCache : IGalaxyHierarchyCache
return _firstLoad.Task.WaitAsync(cancellationToken);
}
/// <summary>
/// Disposes the refresh gate. As a DI singleton the cache is disposed once at host
/// shutdown, after the refresh <see cref="GalaxyHierarchyRefreshService"/> has stopped,
/// so no in-flight refresh can be holding the gate.
/// </summary>
public void Dispose()
{
_refreshGate.Dispose();
}
private async Task RefreshCoreAsync(CancellationToken cancellationToken)
{
// First refresh only: seed the cache from the on-disk snapshot before
@@ -14,7 +14,7 @@ namespace ZB.MOM.WW.GalaxyRepository;
/// both operations are no-ops. The snapshot path is fully consumer-supplied;
/// this store imposes no platform-specific default, so it is cross-platform.
/// </summary>
public sealed class GalaxyHierarchySnapshotStore : IGalaxyHierarchySnapshotStore
public sealed class GalaxyHierarchySnapshotStore : IGalaxyHierarchySnapshotStore, IDisposable
{
/// <summary>
/// On-disk format version. Bump this whenever the persisted shape changes
@@ -138,6 +138,15 @@ public sealed class GalaxyHierarchySnapshotStore : IGalaxyHierarchySnapshotStore
}
}
/// <summary>
/// Disposes the I/O gate. As a DI singleton the store is disposed once at host
/// shutdown, by which point no save/load is in flight.
/// </summary>
public void Dispose()
{
_ioGate.Dispose();
}
/// <summary>On-disk envelope: a schema version plus the snapshot payload.</summary>
private sealed record PersistedFile(int SchemaVersion, GalaxyHierarchySnapshot? Snapshot);
}
@@ -5,7 +5,7 @@ namespace ZB.MOM.WW.GalaxyRepository;
/// <para>
/// <see cref="SectionName"/> is a generic default; the DI extension accepts an explicit
/// configuration section path so a consumer can bind from its own section (e.g.
/// <c>MxGateway:Galaxy</c>).
/// <c>HistorianGateway:Galaxy</c>).
/// </para>
/// </summary>
public sealed class GalaxyRepositoryOptions
@@ -13,7 +13,7 @@ public sealed class GalaxyRepositoryOptions
/// <summary>
/// Generic default configuration section name. The DI extension accepts an explicit
/// section path, so a consumer may bind from a different section (e.g.
/// <c>MxGateway:Galaxy</c>).
/// <c>HistorianGateway:Galaxy</c>).
/// </summary>
public const string SectionName = "GalaxyRepository";