// Licensed to StellaOps under the BUSL-1.1 license. using Dapper; using Microsoft.Extensions.Logging; namespace StellaOps.ReachGraph.Persistence; public sealed partial class PostgresReachGraphRepository { /// public async Task RecordReplayAsync( ReplayLogEntry entry, CancellationToken cancellationToken = default) { ArgumentNullException.ThrowIfNull(entry); await using var connection = await _dataSource .OpenConnectionAsync(cancellationToken) .ConfigureAwait(false); await SetTenantContextAsync(connection, entry.TenantId, cancellationToken).ConfigureAwait(false); var inputsJson = ReachGraphPersistenceCodec.SerializeInputs(entry.InputDigests); var divergenceJson = ReachGraphPersistenceCodec.SerializeDivergence(entry.Divergence); const string sql = """ INSERT INTO reachgraph.replay_log ( subgraph_digest, input_digests, computed_digest, matches, divergence, tenant_id, duration_ms ) VALUES ( @SubgraphDigest, @InputDigests::jsonb, @ComputedDigest, @Matches, @Divergence::jsonb, @TenantId, @DurationMs ) """; var command = new CommandDefinition(sql, new { entry.SubgraphDigest, InputDigests = inputsJson, entry.ComputedDigest, entry.Matches, Divergence = divergenceJson, entry.TenantId, entry.DurationMs }, cancellationToken: cancellationToken); await connection.ExecuteAsync(command).ConfigureAwait(false); _logger.LogInformation( "Recorded replay {Result} for {Digest} (computed: {Computed}, {Duration}ms)", entry.Matches ? "MATCH" : "MISMATCH", entry.SubgraphDigest, entry.ComputedDigest, entry.DurationMs); } }