using Microsoft.Extensions.Configuration;
using ZB.MOM.WW.LocalDb;
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian;
using ZB.MOM.WW.OtOpcUa.Runtime.DeploymentCache;
namespace ZB.MOM.WW.OtOpcUa.Host.Configuration;
///
/// The onReady callback handed to AddZbLocalDb: creates the deployment-cache and
/// alarm store-and-forward tables and opts them into replication.
///
///
///
/// Public rather than internal only so LocalDbSetupTests can drive the production
/// callback directly. Initialising a test database from a hand-written copy of this schema
/// would prove only that the test agrees with itself — the whole value of those tests is
/// that they exercise this method.
///
///
public static class LocalDbSetup
{
///
/// Initialises the local database: DDL first, then replication registration.
///
///
///
/// THE ORDER IS LOAD-BEARING: DDL → RegisterReplicated → writes.
/// RegisterReplicated is what installs the three AFTER triggers that capture
/// changes into the oplog. Any row written before that call is never captured, so it
/// never reaches the peer — silently, and permanently, because nothing ever revisits
/// history. therefore runs last, after every
/// registration — it writes rows, and they must be captured like any other write.
///
///
/// The alarm buffer's tables are created unconditionally, regardless of whether this
/// node has AlarmHistorian:Enabled set. An empty registered table costs three
/// triggers and nothing else, whereas creating it lazily when the sink first appears
/// would mean a node that enables the historian later writes rows before its triggers
/// exist — which is precisely the silent-loss shape above.
///
///
/// The freshly constructed local database.
///
/// Application configuration, read by the legacy migrator for the pre-consolidation queue's
/// path. Required rather than optional: an overload that silently skipped the migration
/// would be one wiring mistake away from discarding a node's undelivered alarm history.
///
public static void OnReady(ILocalDb db, IConfiguration configuration)
{
ArgumentNullException.ThrowIfNull(db);
ArgumentNullException.ThrowIfNull(configuration);
// CreateConnection() hands back an already-open, pragma-configured connection carrying the
// zb_hlc_next() UDF the capture triggers need. Calling Open() on it would throw.
using (var connection = db.CreateConnection())
{
DeploymentCacheSchema.Apply(connection);
AlarmSfSchema.Apply(connection);
}
db.RegisterReplicated(DeploymentCacheSchema.ArtifactsTable);
db.RegisterReplicated(DeploymentCacheSchema.PointerTable);
db.RegisterReplicated(AlarmSfSchema.EventsTable);
// LAST, and only here. This is the one call in OnReady that writes rows.
AlarmSfLegacyMigrator.Migrate(db, configuration);
}
}