New in-process .NET 10 driver project at src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/. The Tier-A replacement for Driver.Galaxy.Host + Driver.Galaxy.Proxy. PR 4.0 ships only the IDriver shape + factory + options; capability bodies (browse, read, write, subscribe, deploy-watch, host probes) land in PRs 4.1–4.7. Files: - Driver.Galaxy.csproj — net10 x64, AnyCPU+x64 platforms, references Core.Abstractions + Core. No MxGatewayClient ProjectReference yet — that comes in PR 4.2 once the gw NuGet package is wired (the user is shipping mxaccessgw on a parallel track). - Config/GalaxyDriverOptions.cs — nested record hierarchy (Gateway/MxAccess/Repository/Reconnect) mirroring the JSON shape spelled out in lmx_mxgw_impl.md PR 4.0 acceptance section. - GalaxyDriver.cs — minimal IDriver impl. Initialize/Shutdown toggle DriverHealth between Healthy/Unknown; Reinitialize bumps the timestamp; GetMemoryFootprint=0 (PR 4.4 wires SubscriptionRegistry size); FlushOptionalCachesAsync no-op. Logs intent on lifecycle calls so partial deployments are diagnosable. - GalaxyDriverFactoryExtensions.cs — JSON parser, default fill-ins, validation throw on missing required fields. Driver type name "GalaxyMxGateway" intentionally distinct from legacy "Galaxy" so both factories coexist during parity testing (Phase 5). PR 4.W's Galaxy:Backend switch picks one or the other. Tests: - 10 tests in Driver.Galaxy.Tests covering minimal-config defaults, full override path, three required-field error cases, factory registration via DriverFactoryRegistry.TryGet, lifecycle health transitions (Init → Shutdown → Reinit), Dispose idempotency, and post-disposal ObjectDisposedException. slnx: registers the new Driver.Galaxy + Driver.Galaxy.Tests projects. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
103 lines
4.4 KiB
C#
103 lines
4.4 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using Microsoft.Extensions.Logging.Abstractions;
|
||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Config;
|
||
|
||
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy;
|
||
|
||
/// <summary>
|
||
/// In-process .NET 10 Galaxy driver — the v2 replacement for the Galaxy.Host /
|
||
/// Galaxy.Proxy pair. PR 4.0 ships the project skeleton with <see cref="IDriver"/>
|
||
/// bodies that wire to a future <c>IGalaxyGatewayClient</c> abstraction. Capability
|
||
/// interfaces (browse, read, write, subscribe, history routing, host probes) land in
|
||
/// PRs 4.1–4.7; the wiring sequence keeps every intermediate state buildable so the
|
||
/// <c>Galaxy:Backend</c> flag (PR 4.W) can flip between legacy-host and mxgateway
|
||
/// for parity testing.
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// This driver is registered as a Tier A in-process driver alongside Modbus / S7 / etc.
|
||
/// The legacy <c>GalaxyProxyDriver</c> (Driver.Galaxy.Proxy) coexists until PR 7.2;
|
||
/// <see cref="GalaxyDriverFactoryExtensions"/> registers under driver-type name
|
||
/// "GalaxyMxGateway" so both paths can be live simultaneously during parity testing.
|
||
/// </remarks>
|
||
public sealed class GalaxyDriver : IDriver, IDisposable
|
||
{
|
||
private readonly string _driverInstanceId;
|
||
private readonly GalaxyDriverOptions _options;
|
||
private readonly ILogger<GalaxyDriver> _logger;
|
||
|
||
private DriverHealth _health = new(DriverState.Unknown, null, null);
|
||
private bool _disposed;
|
||
|
||
public GalaxyDriver(
|
||
string driverInstanceId,
|
||
GalaxyDriverOptions options,
|
||
ILogger<GalaxyDriver>? logger = null)
|
||
{
|
||
_driverInstanceId = !string.IsNullOrWhiteSpace(driverInstanceId)
|
||
? driverInstanceId
|
||
: throw new ArgumentException("Driver instance id required.", nameof(driverInstanceId));
|
||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||
_logger = logger ?? NullLogger<GalaxyDriver>.Instance;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public string DriverInstanceId => _driverInstanceId;
|
||
|
||
/// <inheritdoc />
|
||
public string DriverType => GalaxyDriverFactoryExtensions.DriverTypeName;
|
||
|
||
/// <summary>Test-visible options snapshot.</summary>
|
||
internal GalaxyDriverOptions Options => _options;
|
||
|
||
/// <inheritdoc />
|
||
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
||
{
|
||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||
|
||
// PR 4.0 skeleton — capability bodies (PRs 4.1-4.7) replace this stub with real
|
||
// MxGatewayClient session opening. The skeleton keeps the IDriver shape buildable
|
||
// so the Galaxy:Backend flag (PR 4.W) can register the driver factory now.
|
||
_logger.LogInformation(
|
||
"GalaxyDriver {InstanceId} initializing — endpoint={Endpoint} clientName={ClientName} (skeleton; real gateway connect in PR 4.1+)",
|
||
_driverInstanceId, _options.Gateway.Endpoint, _options.MxAccess.ClientName);
|
||
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
||
{
|
||
// In-place config reapply. PR 4.5's reconnect supervisor will swap the
|
||
// gateway-client options under the lock; for the skeleton we just refresh health.
|
||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public Task ShutdownAsync(CancellationToken cancellationToken)
|
||
{
|
||
if (_disposed) return Task.CompletedTask;
|
||
_logger.LogInformation("GalaxyDriver {InstanceId} shutting down", _driverInstanceId);
|
||
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
/// <inheritdoc />
|
||
public DriverHealth GetHealth() => _health;
|
||
|
||
/// <inheritdoc />
|
||
public long GetMemoryFootprint() => 0; // PR 4.4 sets this from SubscriptionRegistry size.
|
||
|
||
/// <inheritdoc />
|
||
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||
|
||
public void Dispose()
|
||
{
|
||
if (_disposed) return;
|
||
_disposed = true;
|
||
// No owned IDisposables until PR 4.2's GalaxyMxSession lands.
|
||
}
|
||
}
|