packages feed

kiroku-store-0.7.0.0: src/Kiroku/Store/HistoryRetention/Internal.hs

module Kiroku.Store.HistoryRetention.Internal (
    acquireHistoryRetentionLeaseTx,
    renewHistoryRetentionLeaseTx,
    releaseHistoryRetentionLeaseTx,
    historyRetentionLeaseInventoryTx,
    pruneHistoryRetentionLeasesTx,
    lockHistoryRetentionCoordinatorTx,
    activeHistoryRetentionConflictTx,
    lockAffectedStreamsForHardDeleteTx,
) where

import Data.Int (Int64)
import Data.Time.Clock (UTCTime)
import Data.UUID (UUID)
import Data.Vector (Vector)
import Hasql.Transaction qualified as Tx
import Kiroku.Store.HistoryRetention.SQL qualified as SQL
import Kiroku.Store.HistoryRetention.Types

acquireHistoryRetentionLeaseTx :: HistoryRetentionLeaseRequest -> Tx.Transaction HistoryRetentionLease
acquireHistoryRetentionLeaseTx HistoryRetentionLeaseRequest{owner, reason, duration} =
    Tx.statement
        ( historyRetentionLeaseOwnerText owner
        , historyRetentionLeaseReasonText reason
        , historyRetentionLeaseDurationValue duration
        )
        SQL.acquireLeaseStmt

renewHistoryRetentionLeaseTx ::
    HistoryRetentionLeaseHandle ->
    HistoryRetentionLeaseDuration ->
    Tx.Transaction (Either HistoryRetentionRenewalError HistoryRetentionLease)
renewHistoryRetentionLeaseTx HistoryRetentionLeaseHandle{leaseId, owner = requestedOwner} duration = do
    lockHistoryRetentionCoordinatorTx
    current <- Tx.statement (leaseUuid leaseId) SQL.readLeaseForUpdateStmt
    case current of
        Nothing -> pure (Left HistoryRetentionRenewalUnknown)
        Just lease@HistoryRetentionLease{owner = actualOwner, state}
            | actualOwner /= requestedOwner -> pure (Left HistoryRetentionRenewalOwnerMismatch)
            | state == HistoryRetentionLeaseReleased -> pure (Left HistoryRetentionRenewalReleased)
            | state == HistoryRetentionLeaseExpired -> pure (Left HistoryRetentionRenewalExpired)
            | otherwise ->
                Right
                    <$> Tx.statement
                        (leaseUuid leaseId, historyRetentionLeaseDurationValue duration)
                        SQL.renewLeaseStmt

releaseHistoryRetentionLeaseTx ::
    HistoryRetentionLeaseHandle ->
    Tx.Transaction HistoryRetentionReleaseResult
releaseHistoryRetentionLeaseTx HistoryRetentionLeaseHandle{leaseId, owner = requestedOwner} = do
    lockHistoryRetentionCoordinatorTx
    current <- Tx.statement (leaseUuid leaseId) SQL.readLeaseForUpdateStmt
    case current of
        Nothing -> pure HistoryRetentionReleaseUnknown
        Just lease@HistoryRetentionLease{owner = actualOwner, state}
            | actualOwner /= requestedOwner -> pure HistoryRetentionReleaseOwnerMismatch
            | state == HistoryRetentionLeaseReleased -> pure (HistoryRetentionAlreadyReleased lease)
            | state == HistoryRetentionLeaseExpired -> pure (HistoryRetentionReleaseExpired lease)
            | otherwise ->
                HistoryRetentionReleased
                    <$> Tx.statement (leaseUuid leaseId) SQL.releaseLeaseStmt

historyRetentionLeaseInventoryTx ::
    HistoryRetentionInventoryQuery ->
    Tx.Transaction (Vector HistoryRetentionLease)
historyRetentionLeaseInventoryTx HistoryRetentionInventoryQuery{limit} =
    Tx.statement (historyRetentionInventoryLimitValue limit) SQL.leaseInventoryStmt

pruneHistoryRetentionLeasesTx ::
    UTCTime ->
    Tx.Transaction HistoryRetentionPruneResult
pruneHistoryRetentionLeasesTx cutoff = do
    lockHistoryRetentionCoordinatorTx
    Tx.statement cutoff SQL.pruneLeasesStmt

lockHistoryRetentionCoordinatorTx :: Tx.Transaction ()
lockHistoryRetentionCoordinatorTx = do
    _ <- Tx.statement () SQL.lockCoordinatorStmt
    pure ()

activeHistoryRetentionConflictTx :: Tx.Transaction (Maybe HistoryRetentionConflict)
activeHistoryRetentionConflictTx = Tx.statement () SQL.activeConflictStmt

lockAffectedStreamsForHardDeleteTx :: Int64 -> Tx.Transaction ()
lockAffectedStreamsForHardDeleteTx streamId = do
    _ <- Tx.statement streamId SQL.lockAffectedStreamsForHardDeleteStmt
    pure ()

leaseUuid :: HistoryRetentionLeaseId -> UUID
leaseUuid (HistoryRetentionLeaseId value) = value