using Microsoft.Data.Sqlite;
namespace ZB.MOM.WW.OtOpcUa.Runtime.DeploymentCache;
///
/// DDL for the node-local deployment-artifact cache: the chunked artifact table plus the
/// per-cluster current-deployment pointer.
///
///
///
/// Deliberately depends on nothing but so it can be applied
/// to any connection — the host's LocalDbSetup.OnReady in production, and a bare
/// connection in a test — without dragging the DI graph along.
///
///
/// Why the artifact is chunked base64 TEXT and not one BLOB row. Two independent
/// constraints force it. RegisterReplicated rejects BLOB columns outright; and the
/// replication engine batches by row count against gRPC's 4 MB default message cap,
/// so a single multi-megabyte artifact row would simply never be deliverable — at any
/// batch size. A 128 KiB raw chunk is ≈ 171 KB once base64-encoded, which keeps a
/// worst-case batch comfortably inside the cap.
///
///
/// Why no autoincrement PKs. Convergence is last-writer-wins keyed on the primary
/// key. Two nodes independently allocating rowid 7 for different rows would silently
/// overwrite one another. Every key here is TEXT or a composite of caller-supplied values.
///
///
public static class DeploymentCacheSchema
{
/// Table holding the artifact bytes, split into base64 chunks.
public const string ArtifactsTable = "deployment_artifacts";
/// Table holding one current-deployment pointer per cluster.
public const string PointerTable = "deployment_pointer";
///
/// Creates both cache tables if they do not already exist. Idempotent.
///
///
/// An already-open connection. ILocalDb.CreateConnection() hands out open,
/// pragma-configured connections — do not call Open() on one.
///
public static void Apply(SqliteConnection connection)
{
ArgumentNullException.ThrowIfNull(connection);
using var cmd = connection.CreateCommand();
cmd.CommandText = """
CREATE TABLE IF NOT EXISTS deployment_artifacts (
deployment_id TEXT NOT NULL,
chunk_index INTEGER NOT NULL,
cluster_id TEXT NOT NULL,
revision_hash TEXT NOT NULL,
chunk_count INTEGER NOT NULL,
chunk_base64 TEXT NOT NULL,
cached_at_utc TEXT NOT NULL,
PRIMARY KEY (deployment_id, chunk_index)
);
CREATE TABLE IF NOT EXISTS deployment_pointer (
cluster_id TEXT NOT NULL PRIMARY KEY,
deployment_id TEXT NOT NULL,
revision_hash TEXT NOT NULL,
artifact_sha256 TEXT NOT NULL,
applied_at_utc TEXT NOT NULL
);
""";
cmd.ExecuteNonQuery();
}
}