using DodoSSH.Infrastructure; using Microsoft.EntityFrameworkCore; namespace DodoSSH.Api.Features.Teams; /// /// Serialises the writes that decide what a team owns, for the life of the transaction. /// /// /// /// Archiving a team refuses while it owns a vault, and creating a vault refuses on an archived team — but each /// used to check outside any transaction the other could see, so the two could pass each other: the archive /// counted no vaults, a create landed a moment later, and the team was archived with a live vault in it that /// nobody could reach. Both now take this lock inside their transaction and check again under it. /// /// /// The same advisory lock the sync push takes per vault, keyed apart so a team and a vault never share one. /// Requires Multiplexing=false on the connection, as that one does. /// /// internal static class TeamLock { internal static Task AcquireAsync(DodoDbContext database, Guid teamId, CancellationToken cancellationToken) => database.Database.ExecuteSqlAsync( $"SELECT pg_advisory_xact_lock(hashtextextended({"team:" + teamId.ToString()}, 0))", cancellationToken); }