using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Nexus.Api.Data; using Nexus.Api.Services; using Testcontainers.PostgreSql; using Xunit; namespace Nexus.Api.Tests; [Collection(DockerIntegrationTestEnvironment.CollectionName)] public sealed class PostgresOpenClawOperationAuditStoreIntegrationTests { [PostgreSqlIntegrationFact] [Trait("Category", "DockerIntegration")] public async Task Concurrent_store_instances_create_one_claim_and_one_in_doubt_result() { await using var postgres = new PostgreSqlBuilder("postgres:17-alpine") .WithDatabase("nexus_claims") .WithUsername("nexus_test") .WithPassword("nexus_test_password") .Build(); await postgres.StartAsync(); var connectionString = postgres.GetConnectionString(); await using (var db = CreateDatabase(connectionString)) await db.Database.MigrateAsync(); await using var firstProvider = CreateProvider(connectionString); await using var secondProvider = CreateProvider(connectionString); var first = CreateStore(firstProvider); var second = CreateStore(secondProvider); var context = OpenClawInvocationContext.Create( "owner", "postgres-race-key", "postgres-race-correlation"); var operation = new OpenClawOperationDescriptor( "cron.run", "cron-job", "job-1", OpenClawInvocationContextFactory.Hash("same-intent")); var results = await Task.WhenAll( first.ClaimAsync(context, operation), second.ClaimAsync(context, operation)); Assert.Single( results, item => item.Disposition == OpenClawOperationClaimDisposition.Started); Assert.Single( results, item => item.Disposition == OpenClawOperationClaimDisposition.InDoubt); await using var verification = CreateDatabase(connectionString); Assert.Single(await verification.OperationClaims.ToArrayAsync()); } private static NexusDbContext CreateDatabase(string connectionString) => new(new DbContextOptionsBuilder() .UseNpgsql(connectionString) .Options); private static ServiceProvider CreateProvider(string connectionString) { var services = new ServiceCollection(); services.AddDbContext(options => options.UseNpgsql(connectionString)); return services.BuildServiceProvider(); } private static PostgresOpenClawOperationAuditStore CreateStore( ServiceProvider provider) => new( provider.GetRequiredService(), Options.Create(new GatewayConnectorOptions())); }