| | | 1 | | using ArturRios.Heimdall.Domain.Entities; |
| | | 2 | | using ArturRios.Heimdall.Domain.Enums; |
| | | 3 | | |
| | | 4 | | namespace ArturRios.Heimdall.Domain.Persistence; |
| | | 5 | | |
| | | 6 | | /// <summary>What <see cref="IScopeOwnerInvitations.OpenAsync" /> did: the pair's open invitation, and whether this call |
| | 74 | 7 | | public sealed record ScopeOwnerInvitationOpening(ScopeOwnerInvitation Invitation, bool Created); |
| | | 8 | | |
| | | 9 | | /// <summary> |
| | | 10 | | /// The writes that end a scope owner invitation (FR-SC-17, FR-SC-18). Each end is one conditional |
| | | 11 | | /// <c>UPDATE … WHERE</c> on an open invitation, as <see cref="IAtomicWrites" />'s writes are, so of any |
| | | 12 | | /// number of racing answers, withdrawals and voids exactly one takes effect and every other is told so. |
| | | 13 | | /// </summary> |
| | | 14 | | public interface IScopeOwnerInvitations |
| | | 15 | | { |
| | | 16 | | /// <summary> |
| | | 17 | | /// Opens <paramref name="invitation" /> for its scope and invitee, or answers with the one already open |
| | | 18 | | /// (<c>Created = false</c>). An expired, unended invitation of the pair is first ended at its expiry with |
| | | 19 | | /// no outcome, since it still holds the pair's slot. Two simultaneous calls create one row between them. |
| | | 20 | | /// </summary> |
| | | 21 | | Task<ScopeOwnerInvitationOpening> OpenAsync(ScopeOwnerInvitation invitation, DateTime now); |
| | | 22 | | |
| | | 23 | | /// <summary> |
| | | 24 | | /// Ends the invitation with <paramref name="outcome" /> — declined, withdrawn or voided — if it is still |
| | | 25 | | /// open at <paramref name="now" />. <c>false</c> means it had already ended or expired, and nothing was |
| | | 26 | | /// written. Acceptance writes an ownership too and is <see cref="TryAcceptAsync" />'s. |
| | | 27 | | /// </summary> |
| | | 28 | | /// <exception cref="ArgumentException"><paramref name="outcome" /> is Accepted.</exception> |
| | | 29 | | Task<bool> TryEndAsync(ScopeOwnerInvitation invitation, ScopeOwnerInvitationOutcomes outcome, DateTime now); |
| | | 30 | | |
| | | 31 | | /// <summary> |
| | | 32 | | /// In one transaction: ends the invitation as accepted — only while it is open, its scope is live and |
| | | 33 | | /// its invitee <see cref="ScopeOwnerInvitation.EligibleInvitee" /> — and, only if that write took, |
| | | 34 | | /// inserts the <c>SCOPE_OWNER</c> row (a no-op when it exists). <c>false</c> means nothing was written. |
| | | 35 | | /// </summary> |
| | | 36 | | Task<bool> TryAcceptAsync(ScopeOwnerInvitation invitation, DateTime now); |
| | | 37 | | |
| | | 38 | | /// <summary> |
| | | 39 | | /// Anonymisation (NFR-20), in one transaction: voids every unended invitation whose invitee is among |
| | | 40 | | /// <paramref name="personIds" />, and clears those persons as inviter on every invitation. Answers |
| | | 41 | | /// with the public ids of exactly the invitations this call voided, never one a racing answer ended |
| | | 42 | | /// first, so each can be audited as voided. |
| | | 43 | | /// </summary> |
| | | 44 | | Task<IReadOnlyList<Guid>> ForgetPersonsAsync(IReadOnlyCollection<long> personIds, DateTime now); |
| | | 45 | | } |