Specify fenced activation and source credential contracts

Define bounded reservation recovery, exact activation replay fencing, immutable source identities, and deployment-owned secret and target policy boundaries. Align the OpenAPI contract and add a split-store activation safety refinement.
This commit is contained in:
ms2k 2026-07-14 18:12:28 +09:00
commit 033cfeaac6
13 changed files with 877 additions and 49 deletions

View file

@ -14,6 +14,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE
@ -42,6 +43,7 @@ PROPERTIES
FailureDispositionHonored
EventuallyDispatched
EventuallyReaped
EventuallyAuthorizedResolved
EventuallyTerminal
EventuallyNonWinnerStagingCleaned
EventuallySystemQuiescent

View file

@ -29,7 +29,7 @@ EXTENDS Naturals, FiniteSets, TLC
CONSTANTS
Jobs, Workers, InitialWorkers, NoJob, NoWorker,
MaxAttempts, MaxProgress, LeaseLimit,
MaxAttempts, MaxProgress, LeaseLimit, ReservationLimit,
LocalLimit, GlobalLimit, FaultsEnabled, FaultServices,
MaxCoordLosses, MaxPartitions
@ -40,6 +40,7 @@ ASSUME /\ Jobs # {}
/\ MaxAttempts \in Nat \ {0}
/\ MaxProgress \in Nat \ {0}
/\ LeaseLimit \in Nat \ {0}
/\ ReservationLimit \in Nat \ {0}
/\ LocalLimit \in Nat \ {0}
/\ GlobalLimit \in Nat \ {0}
/\ FaultsEnabled \in BOOLEAN
@ -119,7 +120,7 @@ VARIABLES
checkpointValid,
\* CoordinationStore (reconstructible).
queued, reservation, leaseState, leaseAge, cancelNotice,
queued, reservation, reservationAge, leaseState, leaseAge, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount,
\* Worker incarnations, per-service links, partition budget.
@ -133,7 +134,7 @@ durableVars ==
<<phase, cancelRequested, currentToken, authority, dispatchNeeded,
committedAttempt, checkpoint, checkpointValid>>
coordinationVars ==
<<queued, reservation, leaseState, leaseAge, cancelNotice,
<<queued, reservation, reservationAge, leaseState, leaseAge, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
workerVars == <<workerState, links, partitionCount>>
attemptVars ==
@ -168,6 +169,7 @@ OtherCapacity(w) ==
CoordinationClean(j) ==
/\ ~queued[j]
/\ reservation[j] = NoWorker
/\ reservationAge[j] = 0
/\ ~cancelNotice[j]
/\ liveProgress[j] = 0
/\ liveProgressAttempt[j] = NoAttempt
@ -195,6 +197,7 @@ Init ==
/\ checkpointValid = [j \in Jobs |-> FALSE]
/\ queued = [j \in Jobs |-> FALSE]
/\ reservation = [j \in Jobs |-> NoWorker]
/\ reservationAge = [j \in Jobs |-> 0]
/\ leaseState = [a \in AttemptIds |-> NoLease]
/\ leaseAge = [a \in AttemptIds |-> 0]
/\ cancelNotice = [j \in Jobs |-> FALSE]
@ -222,7 +225,7 @@ Enqueue(j) ==
/\ reservation[j] = NoWorker
/\ queued' = [queued EXCEPT ![j] = TRUE]
/\ UNCHANGED durableVars
/\ UNCHANGED <<reservation, leaseState, leaseAge, cancelNotice,
/\ UNCHANGED <<reservation, reservationAge, leaseState, leaseAge, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -235,6 +238,7 @@ Reserve(j, w) ==
/\ CapacityAvailable(w)
/\ queued' = [queued EXCEPT ![j] = FALSE]
/\ reservation' = [reservation EXCEPT ![j] = w]
/\ reservationAge' = [reservationAge EXCEPT ![j] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<leaseState, leaseAge, cancelNotice, liveProgress,
liveProgressAttempt, coordLossCount>>
@ -289,6 +293,7 @@ ActivateAttempt(a) ==
/\ workerState[w] = WorkerUp
/\ CanReach(w, CoordSvc)
/\ reservation' = [reservation EXCEPT ![j] = NoWorker]
/\ reservationAge' = [reservationAge EXCEPT ![j] = 0]
/\ leaseState' = [leaseState EXCEPT ![a] = LeaseLive]
/\ leaseAge' = [leaseAge EXCEPT ![a] = 0]
/\ liveProgress' = [liveProgress EXCEPT ![j] = attemptProgress[a]]
@ -309,24 +314,44 @@ RenewLease(a) ==
/\ CanReach(w, CoordSvc)
/\ leaseAge' = [leaseAge EXCEPT ![a] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, leaseState, cancelNotice,
/\ UNCHANGED <<queued, reservation, reservationAge, leaseState, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
Tick ==
/\ \E a \in AttemptIds :
leaseState[a] = LeaseLive /\ leaseAge[a] < LeaseLimit
/\ (\E a \in AttemptIds :
leaseState[a] = LeaseLive /\ leaseAge[a] < LeaseLimit)
\/ (\E j \in Jobs :
reservation[j] # NoWorker /\ reservationAge[j] < ReservationLimit)
/\ leaseAge' =
[a \in AttemptIds |->
IF leaseState[a] = LeaseLive /\ leaseAge[a] < LeaseLimit
THEN leaseAge[a] + 1 ELSE leaseAge[a]]
/\ reservationAge' =
[j \in Jobs |->
IF reservation[j] # NoWorker
/\ reservationAge[j] < ReservationLimit
THEN reservationAge[j] + 1 ELSE reservationAge[j]]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, leaseState, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
\* Reservation expiry is coordination-only. Queued jobs become eligible for
\* Enqueue; authorized attempts become eligible for ReapLostAttempt.
ExpireReservation(j) ==
/\ reservation[j] # NoWorker
/\ reservationAge[j] = ReservationLimit
/\ reservation' = [reservation EXCEPT ![j] = NoWorker]
/\ reservationAge' = [reservationAge EXCEPT ![j] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, leaseState, leaseAge, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
\* Lease expiry does not clear live progress: product may retain a stale
\* (attempt, bytes) hint until overwrite, reader discard, or terminal GC.
ExpireLease(a) ==
@ -335,7 +360,7 @@ ExpireLease(a) ==
/\ leaseState' = [leaseState EXCEPT ![a] = LeaseExpired]
/\ leaseAge' = [leaseAge EXCEPT ![a] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, cancelNotice, liveProgress,
/\ UNCHANGED <<queued, reservation, reservationAge, cancelNotice, liveProgress,
liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -347,6 +372,7 @@ LoseCoordinationState ==
/\ coordLossCount < MaxCoordLosses
/\ queued' = [j \in Jobs |-> FALSE]
/\ reservation' = [j \in Jobs |-> NoWorker]
/\ reservationAge' = [j \in Jobs |-> 0]
/\ leaseState' =
[a \in AttemptIds |->
IF leaseState[a] = LeaseLive THEN LeaseExpired
@ -419,6 +445,7 @@ ReleaseReservation(j) ==
\/ (authority[j] # NoAttempt
/\ attemptState[authority[j]] # AttemptAuthorized))
/\ reservation' = [reservation EXCEPT ![j] = NoWorker]
/\ reservationAge' = [reservationAge EXCEPT ![j] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, leaseState, leaseAge, cancelNotice,
liveProgress, liveProgressAttempt, coordLossCount>>
@ -502,7 +529,7 @@ PublishCancelNotice(j) ==
/\ ~cancelNotice[j]
/\ cancelNotice' = [cancelNotice EXCEPT ![j] = TRUE]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, leaseState, leaseAge, liveProgress,
/\ UNCHANGED <<queued, reservation, reservationAge, leaseState, leaseAge, liveProgress,
liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -531,7 +558,7 @@ ReleaseLease(a) ==
/\ leaseState' = [leaseState EXCEPT ![a] = LeaseExpired]
/\ leaseAge' = [leaseAge EXCEPT ![a] = 0]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, cancelNotice, liveProgress,
/\ UNCHANGED <<queued, reservation, reservationAge, cancelNotice, liveProgress,
liveProgressAttempt, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -546,7 +573,7 @@ ClearStaleLiveProgress(j) ==
/\ liveProgressAttempt' =
[liveProgressAttempt EXCEPT ![j] = NoAttempt]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, leaseState, leaseAge,
/\ UNCHANGED <<queued, reservation, reservationAge, leaseState, leaseAge,
cancelNotice, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -557,6 +584,7 @@ CleanTerminalCoordination(j) ==
\/ liveProgress[j] # 0 \/ liveProgressAttempt[j] # NoAttempt)
/\ queued' = [queued EXCEPT ![j] = FALSE]
/\ reservation' = [reservation EXCEPT ![j] = NoWorker]
/\ reservationAge' = [reservationAge EXCEPT ![j] = 0]
/\ cancelNotice' = [cancelNotice EXCEPT ![j] = FALSE]
/\ liveProgress' = [liveProgress EXCEPT ![j] = 0]
/\ liveProgressAttempt' =
@ -628,7 +656,7 @@ ReportProgress(a) ==
/\ liveProgressAttempt' =
[liveProgressAttempt EXCEPT ![j] = a]
/\ UNCHANGED durableVars
/\ UNCHANGED <<queued, reservation, leaseState, leaseAge,
/\ UNCHANGED <<queued, reservation, reservationAge, leaseState, leaseAge,
cancelNotice, coordLossCount>>
/\ UNCHANGED workerVars
/\ UNCHANGED attemptVars
@ -774,6 +802,7 @@ Next ==
\/ \E a \in AttemptIds : RenewLease(a)
\/ Tick
\/ \E a \in AttemptIds : ExpireLease(a)
\/ \E j \in Jobs : ExpireReservation(j)
\/ LoseCoordinationState
\/ \E w \in Workers, s \in Services : DropLink(w, s)
\/ \E w \in Workers, s \in Services : RestoreLink(w, s)
@ -812,6 +841,7 @@ Fairness ==
/\ \A j \in Jobs : SF_vars(ExecuteJob(j))
/\ \A a \in AttemptIds : WF_vars(ProcessOutcome(a))
/\ \A a \in AttemptIds : WF_vars(ExpireLease(a))
/\ \A j \in Jobs : WF_vars(ExpireReservation(j))
/\ \A a \in AttemptIds : WF_vars(CooperativeStop(a))
/\ \A a \in AttemptIds : WF_vars(ReleaseLease(a))
/\ \A a \in AttemptIds : WF_vars(CleanupStage(a))
@ -840,6 +870,7 @@ TypeOK ==
/\ checkpointValid \in [Jobs -> BOOLEAN]
/\ queued \in [Jobs -> BOOLEAN]
/\ reservation \in [Jobs -> Workers \cup {NoWorker}]
/\ reservationAge \in [Jobs -> 0..ReservationLimit]
/\ leaseState \in [AttemptIds -> LeaseStates]
/\ leaseAge \in [AttemptIds -> 0..LeaseLimit]
/\ cancelNotice \in [Jobs -> BOOLEAN]
@ -874,6 +905,7 @@ StateConsistency ==
/\ (committedAttempt[j] # NoAttempt <=> phase[j] = Succeeded)
/\ (phase[j] = Queued => dispatchNeeded[j])
/\ (reservation[j] # NoWorker => ~queued[j])
/\ (reservation[j] = NoWorker => reservationAge[j] = 0)
/\ \A a \in AttemptIds :
/\ (attemptState[a] = AttemptUnused <=>
attemptWorker[a] = NoWorker)
@ -1024,6 +1056,13 @@ EventuallyReaped ==
\A a \in AttemptIds :
(CurrentAuthority(a) /\ leaseState[a] # LeaseLive)
~> (~CurrentAuthority(a) \/ Terminal(JobOf(a)))
EventuallyAuthorizedResolved ==
RecoveryAssumption =>
\A a \in AttemptIds :
(CurrentAuthority(a) /\ attemptState[a] = AttemptAuthorized)
~> (attemptState[a] = AttemptExecuting
\/ ~CurrentAuthority(a)
\/ Terminal(JobOf(a)))
EventuallyTerminal ==
RecoveryAssumption => \A j \in Jobs : <>Terminal(j)

View file

@ -0,0 +1,28 @@
SPECIFICATION Spec
CHECK_DEADLOCK TRUE
CONSTANTS
Claims = {c1}
Fences = {f1, f2}
Workers = {w1, w2}
Operations = {op1, op2}
NoWorker = NoWorker
NoOwner = NoOwner
NoRequest = NoRequest
NoResponse = NoResponse
Accepted = Accepted
Rejected = Rejected
INVARIANTS
TypeOK
LiveLeaseMatchesAuthority
ExecutingIsCommitted
AcceptedResponseIsExactReplay
ConflictIsChangedRequest
ReapedClaimHasNoActivationEffect
ReapedCoordinationIsClean
PROPERTIES
ActivationAppliesAtMostOnce
OperationRequestIsImmutable

View file

@ -0,0 +1,307 @@
---------------------- MODULE RemoraClaimActivation ----------------------
EXTENDS Naturals
\* Split-store refinement of the atomic JobProtocol ActivateAttempt action.
\* Durable execution is the linearization point; lease creation alone is not authority.
CONSTANTS
Claims, Fences, Workers, Operations,
NoWorker, NoOwner, NoRequest, NoResponse, Accepted, Rejected
RequestKeys == Claims \X Fences \X Workers
ASSUME /\ Claims # {}
/\ Fences # {}
/\ Workers # {}
/\ Operations # {}
/\ NoWorker \notin Workers
/\ NoRequest \notin RequestKeys
Authorized == "Authorized"
Executing == "Executing"
Reaped == "Reaped"
DurableStates == {Authorized, Executing, Reaped}
Idle == "Idle"
Validated == "Validated"
LeaseCreated == "LeaseCreated"
Committed == "Committed"
Finished == "Finished"
ActivationStages == {Idle, Validated, LeaseCreated, Committed, Finished}
Activator == "Activator"
Recovery == "Recovery"
LockOwners == {NoOwner, Activator, Recovery}
Responses == {NoResponse, Accepted, Rejected}
VARIABLES
durableState, attemptFence, attemptWorker, reservation, lease,
activationStage, durableLock, operationRequest, operationResponse,
conflictRequest, activationEffectCount
vars == <<durableState, attemptFence, attemptWorker, reservation, lease,
activationStage, durableLock, operationRequest, operationResponse,
conflictRequest, activationEffectCount>>
Request(c, f, w) == <<c, f, w>>
ExactRequest(c) == Request(c, attemptFence[c], attemptWorker[c])
Init ==
/\ durableState = [c \in Claims |-> Authorized]
/\ attemptFence \in [Claims -> Fences]
/\ attemptWorker \in [Claims -> Workers]
/\ reservation = attemptWorker
/\ lease = [c \in Claims |-> NoWorker]
/\ activationStage = [c \in Claims |-> Idle]
/\ durableLock = [c \in Claims |-> NoOwner]
/\ operationRequest = [op \in Operations |-> NoRequest]
/\ operationResponse = [op \in Operations |-> NoResponse]
/\ conflictRequest = [op \in Operations |-> NoRequest]
/\ activationEffectCount = [c \in Claims |-> 0]
BindOperation(op, c, f, w) ==
/\ operationRequest[op] = NoRequest
/\ operationRequest' =
[operationRequest EXCEPT ![op] = Request(c, f, w)]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, durableLock, operationResponse,
conflictRequest, activationEffectCount>>
RejectOperationReuse(op, c, f, w) ==
/\ operationRequest[op] # NoRequest
/\ operationRequest[op] # Request(c, f, w)
/\ conflictRequest' =
[conflictRequest EXCEPT ![op] = Request(c, f, w)]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, durableLock, operationRequest,
operationResponse, activationEffectCount>>
StartActivation(op, c, f, w) ==
/\ operationRequest[op] = Request(c, f, w)
/\ operationResponse[op] = NoResponse
/\ Request(c, f, w) = ExactRequest(c)
/\ activationStage[c] = Idle
/\ durableState[c] = Authorized
/\ reservation[c] = w
/\ activationStage' = [activationStage EXCEPT ![c] = Validated]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, durableLock, operationRequest, operationResponse,
conflictRequest, activationEffectCount>>
CreateLease(c) ==
LET w == attemptWorker[c]
IN /\ activationStage[c] = Validated
/\ durableState[c] = Authorized
/\ reservation[c] = w
/\ lease[c] = NoWorker
/\ lease' = [lease EXCEPT ![c] = w]
/\ activationStage' = [activationStage EXCEPT ![c] = LeaseCreated]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
durableLock, operationRequest, operationResponse,
conflictRequest, activationEffectCount>>
AcquireActivationLock(c) ==
/\ activationStage[c] = LeaseCreated
/\ durableState[c] = Authorized
/\ durableLock[c] = NoOwner
/\ durableLock' = [durableLock EXCEPT ![c] = Activator]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, operationRequest,
operationResponse, conflictRequest,
activationEffectCount>>
LoseActivatorLock(c) ==
/\ durableLock[c] = Activator
/\ durableLock' = [durableLock EXCEPT ![c] = NoOwner]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, operationRequest,
operationResponse, conflictRequest,
activationEffectCount>>
CommitActivation(c) ==
LET w == attemptWorker[c]
IN /\ activationStage[c] = LeaseCreated
/\ durableLock[c] = Activator
/\ durableState[c] = Authorized
/\ reservation[c] = w
/\ lease[c] = w
/\ durableState' = [durableState EXCEPT ![c] = Executing]
/\ reservation' = [reservation EXCEPT ![c] = NoWorker]
/\ activationStage' = [activationStage EXCEPT ![c] = Committed]
/\ durableLock' = [durableLock EXCEPT ![c] = NoOwner]
/\ activationEffectCount' =
[activationEffectCount EXCEPT ![c] = @ + 1]
/\ UNCHANGED <<attemptFence, attemptWorker, lease,
operationRequest, operationResponse, conflictRequest>>
ReplayActivation(op, c, f, w) ==
/\ operationRequest[op] = Request(c, f, w)
/\ Request(c, f, w) = ExactRequest(c)
/\ durableState[c] = Executing
/\ lease[c] = w
/\ activationEffectCount[c] = 1
/\ operationResponse' =
[operationResponse EXCEPT ![op] = Accepted]
/\ activationStage' = [activationStage EXCEPT ![c] = Finished]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, durableLock, operationRequest, conflictRequest,
activationEffectCount>>
RejectPrecondition(op, c, f, w) ==
/\ operationRequest[op] = Request(c, f, w)
/\ operationResponse[op] = NoResponse
/\ \/ Request(c, f, w) # ExactRequest(c)
\/ durableState[c] = Reaped
\/ /\ durableState[c] = Executing
/\ lease[c] # w
/\ operationResponse' =
[operationResponse EXCEPT ![op] = Rejected]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, durableLock, operationRequest,
conflictRequest, activationEffectCount>>
ExpireReservation(c) ==
/\ durableState[c] = Authorized
/\ reservation[c] # NoWorker
/\ lease[c] = NoWorker
/\ reservation' = [reservation EXCEPT ![c] = NoWorker]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, lease,
activationStage, durableLock, operationRequest,
operationResponse, conflictRequest,
activationEffectCount>>
ExpireLease(c) ==
/\ durableState[c] = Executing
/\ lease[c] = attemptWorker[c]
/\ lease' = [lease EXCEPT ![c] = NoWorker]
/\ operationResponse' =
[op \in Operations |->
IF operationResponse[op] = Accepted
/\ operationRequest[op][1] = c
THEN NoResponse ELSE operationResponse[op]]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
activationStage, durableLock, operationRequest,
conflictRequest, activationEffectCount>>
AcquireRecoveryLock(c) ==
/\ durableState[c] = Authorized
/\ durableLock[c] = NoOwner
/\ durableLock' = [durableLock EXCEPT ![c] = Recovery]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
lease, activationStage, operationRequest,
operationResponse, conflictRequest,
activationEffectCount>>
FinishRecovery(c) ==
/\ durableLock[c] = Recovery
/\ durableState[c] = Authorized
/\ durableState' = [durableState EXCEPT ![c] = Reaped]
/\ reservation' = [reservation EXCEPT ![c] = NoWorker]
/\ lease' = [lease EXCEPT ![c] = NoWorker]
/\ durableLock' = [durableLock EXCEPT ![c] = NoOwner]
/\ UNCHANGED <<attemptFence, attemptWorker, activationStage,
operationRequest, operationResponse, conflictRequest,
activationEffectCount>>
CompensateRejectedActivation(c) ==
LET w == attemptWorker[c]
IN /\ durableState[c] = Reaped
/\ activationStage[c] \in {Validated, LeaseCreated}
/\ lease[c] \in {NoWorker, w}
/\ lease' = [lease EXCEPT ![c] = NoWorker]
/\ activationStage' = [activationStage EXCEPT ![c] = Finished]
/\ UNCHANGED <<durableState, attemptFence, attemptWorker, reservation,
durableLock, operationRequest, operationResponse,
conflictRequest, activationEffectCount>>
Done ==
/\ \A c \in Claims : durableState[c] \in {Executing, Reaped}
/\ UNCHANGED vars
Next ==
\/ \E op \in Operations, c \in Claims, f \in Fences, w \in Workers :
BindOperation(op, c, f, w)
\/ \E op \in Operations, c \in Claims, f \in Fences, w \in Workers :
RejectOperationReuse(op, c, f, w)
\/ \E op \in Operations, c \in Claims, f \in Fences, w \in Workers :
StartActivation(op, c, f, w)
\/ \E c \in Claims : CreateLease(c)
\/ \E c \in Claims : AcquireActivationLock(c)
\/ \E c \in Claims : LoseActivatorLock(c)
\/ \E c \in Claims : CommitActivation(c)
\/ \E op \in Operations, c \in Claims, f \in Fences, w \in Workers :
ReplayActivation(op, c, f, w)
\/ \E op \in Operations, c \in Claims, f \in Fences, w \in Workers :
RejectPrecondition(op, c, f, w)
\/ \E c \in Claims : ExpireReservation(c)
\/ \E c \in Claims : ExpireLease(c)
\/ \E c \in Claims : AcquireRecoveryLock(c)
\/ \E c \in Claims : FinishRecovery(c)
\/ \E c \in Claims : CompensateRejectedActivation(c)
\/ Done
Spec == Init /\ [][Next]_vars
TypeOK ==
/\ durableState \in [Claims -> DurableStates]
/\ attemptFence \in [Claims -> Fences]
/\ attemptWorker \in [Claims -> Workers]
/\ reservation \in [Claims -> Workers \cup {NoWorker}]
/\ lease \in [Claims -> Workers \cup {NoWorker}]
/\ activationStage \in [Claims -> ActivationStages]
/\ durableLock \in [Claims -> LockOwners]
/\ operationRequest \in [Operations -> RequestKeys \cup {NoRequest}]
/\ operationResponse \in [Operations -> Responses]
/\ conflictRequest \in [Operations -> RequestKeys \cup {NoRequest}]
/\ activationEffectCount \in [Claims -> 0..1]
LiveLeaseMatchesAuthority ==
\A c \in Claims :
lease[c] # NoWorker => lease[c] = attemptWorker[c]
ExecutingIsCommitted ==
\A c \in Claims :
durableState[c] = Executing =>
/\ reservation[c] = NoWorker
/\ activationStage[c] \in {Committed, Finished}
/\ activationEffectCount[c] = 1
AcceptedResponseIsExactReplay ==
\A op \in Operations :
operationResponse[op] = Accepted =>
\E c \in Claims :
/\ operationRequest[op] = ExactRequest(c)
/\ durableState[c] = Executing
/\ lease[c] = attemptWorker[c]
/\ activationEffectCount[c] = 1
ConflictIsChangedRequest ==
\A op \in Operations :
conflictRequest[op] # NoRequest =>
/\ operationRequest[op] # NoRequest
/\ conflictRequest[op] # operationRequest[op]
ReapedClaimHasNoActivationEffect ==
\A c \in Claims :
durableState[c] = Reaped => activationEffectCount[c] = 0
ReapedCoordinationIsClean ==
\A c \in Claims :
durableState[c] = Reaped =>
/\ reservation[c] = NoWorker
/\ lease[c] = NoWorker
ActivationAppliesAtMostOnceAction ==
\A c \in Claims :
activationEffectCount[c] = 1 => activationEffectCount'[c] = 1
ActivationAppliesAtMostOnce == [][ActivationAppliesAtMostOnceAction]_vars
OperationRequestIsImmutableAction ==
\A op \in Operations :
operationRequest[op] # NoRequest =>
operationRequest'[op] = operationRequest[op]
OperationRequestIsImmutable == [][OperationRequestIsImmutableAction]_vars
=============================================================================

View file

@ -14,6 +14,7 @@ CONSTANTS
MaxAttempts = 1
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 2
FaultsEnabled = FALSE

View file

@ -11,6 +11,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = FALSE

View file

@ -13,6 +13,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE

View file

@ -13,6 +13,7 @@ CONSTANTS
MaxAttempts = 3
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE

View file

@ -12,6 +12,7 @@ CONSTANTS
MaxAttempts = 1
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 2
GlobalLimit = 1
FaultsEnabled = FALSE

View file

@ -12,6 +12,7 @@ CONSTANTS
MaxAttempts = 1
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 3
FaultsEnabled = FALSE

View file

@ -12,6 +12,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE

View file

@ -14,6 +14,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 2
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE

View file

@ -13,6 +13,7 @@ CONSTANTS
MaxAttempts = 2
MaxProgress = 1
LeaseLimit = 1
ReservationLimit = 1
LocalLimit = 1
GlobalLimit = 1
FaultsEnabled = TRUE