Model checkpoint staging ownership transfer
This commit is contained in:
parent
ebf818d23c
commit
16cba3c317
13 changed files with 111 additions and 16 deletions
|
|
@ -35,6 +35,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ CredentialIntents ==
|
||||||
VARIABLES
|
VARIABLES
|
||||||
\* DurableStore authority.
|
\* DurableStore authority.
|
||||||
phase, cancelRequested, currentToken, authority, dispatchNeeded,
|
phase, cancelRequested, currentToken, authority, dispatchNeeded,
|
||||||
committedAttempt, checkpoint,
|
committedAttempt, checkpoint, checkpointStageOwner,
|
||||||
\* Abstracts the complete source-identity and destination-state proof.
|
\* Abstracts the complete source-identity and destination-state proof.
|
||||||
checkpointValid,
|
checkpointValid,
|
||||||
|
|
||||||
|
|
@ -157,7 +157,7 @@ VARIABLES
|
||||||
|
|
||||||
durableVars ==
|
durableVars ==
|
||||||
<<phase, cancelRequested, currentToken, authority, dispatchNeeded,
|
<<phase, cancelRequested, currentToken, authority, dispatchNeeded,
|
||||||
committedAttempt, checkpoint, checkpointValid>>
|
committedAttempt, checkpoint, checkpointStageOwner, checkpointValid>>
|
||||||
coordinationVars ==
|
coordinationVars ==
|
||||||
<<queued, reservation, reservationAge, leaseState, leaseAge, cancelNotice,
|
<<queued, reservation, reservationAge, leaseState, leaseAge, cancelNotice,
|
||||||
liveProgress, liveProgressAttempt, coordLossCount>>
|
liveProgress, liveProgressAttempt, coordLossCount>>
|
||||||
|
|
@ -226,6 +226,7 @@ Init ==
|
||||||
/\ dispatchNeeded = [j \in Jobs |-> TRUE]
|
/\ dispatchNeeded = [j \in Jobs |-> TRUE]
|
||||||
/\ committedAttempt = [j \in Jobs |-> NoAttempt]
|
/\ committedAttempt = [j \in Jobs |-> NoAttempt]
|
||||||
/\ checkpoint = [j \in Jobs |-> 0]
|
/\ checkpoint = [j \in Jobs |-> 0]
|
||||||
|
/\ checkpointStageOwner = [j \in Jobs |-> NoAttempt]
|
||||||
/\ checkpointValid = [j \in Jobs |-> FALSE]
|
/\ checkpointValid = [j \in Jobs |-> FALSE]
|
||||||
/\ queued = [j \in Jobs |-> FALSE]
|
/\ queued = [j \in Jobs |-> FALSE]
|
||||||
/\ reservation = [j \in Jobs |-> NoWorker]
|
/\ reservation = [j \in Jobs |-> NoWorker]
|
||||||
|
|
@ -291,6 +292,9 @@ AuthorizeAttempt(j, w) ==
|
||||||
/\ CanReach(w, DurableSvc)
|
/\ CanReach(w, DurableSvc)
|
||||||
/\ currentToken[j] < MaxAttempts
|
/\ currentToken[j] < MaxAttempts
|
||||||
/\ attemptState[a] = AttemptUnused
|
/\ attemptState[a] = AttemptUnused
|
||||||
|
/\ IF checkpointValid[j]
|
||||||
|
THEN attemptState[checkpointStageOwner[j]] = AttemptStopped
|
||||||
|
ELSE TRUE
|
||||||
/\ phase' = [phase EXCEPT ![j] = Running]
|
/\ phase' = [phase EXCEPT ![j] = Running]
|
||||||
/\ currentToken' = [currentToken EXCEPT ![j] = @ + 1]
|
/\ currentToken' = [currentToken EXCEPT ![j] = @ + 1]
|
||||||
/\ authority' = [authority EXCEPT ![j] = a]
|
/\ authority' = [authority EXCEPT ![j] = a]
|
||||||
|
|
@ -307,11 +311,15 @@ AuthorizeAttempt(j, w) ==
|
||||||
[resumedFromCheckpoint EXCEPT
|
[resumedFromCheckpoint EXCEPT
|
||||||
![a] = checkpointValid[j] /\ checkpoint[j] > 0]
|
![a] = checkpointValid[j] /\ checkpoint[j] > 0]
|
||||||
/\ stageState' =
|
/\ stageState' =
|
||||||
[stageState EXCEPT
|
IF checkpointValid[j]
|
||||||
![a] = IF ~checkpointValid[j] \/ checkpoint[j] = 0
|
THEN [stageState EXCEPT
|
||||||
THEN StageNone
|
![checkpointStageOwner[j]] = StageNone,
|
||||||
ELSE IF checkpoint[j] = MaxProgress
|
![a] = IF checkpoint[j] = MaxProgress
|
||||||
THEN StageComplete ELSE StagePartial]
|
THEN StageComplete ELSE StagePartial]
|
||||||
|
ELSE [stageState EXCEPT ![a] = StageNone]
|
||||||
|
/\ checkpointStageOwner' =
|
||||||
|
[checkpointStageOwner EXCEPT
|
||||||
|
![j] = IF checkpointValid[j] THEN a ELSE NoAttempt]
|
||||||
/\ UNCHANGED <<cancelRequested, committedAttempt, checkpoint,
|
/\ UNCHANGED <<cancelRequested, committedAttempt, checkpoint,
|
||||||
checkpointValid>>
|
checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
|
|
@ -512,7 +520,8 @@ ReapLostAttempt(a) ==
|
||||||
![a] = IF attemptState[a] = AttemptAuthorized
|
![a] = IF attemptState[a] = AttemptAuthorized
|
||||||
THEN AttemptStopped ELSE @]
|
THEN AttemptStopped ELSE @]
|
||||||
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
||||||
committedAttempt, checkpoint, checkpointValid>>
|
committedAttempt, checkpoint, checkpointStageOwner,
|
||||||
|
checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
/\ UNCHANGED workerVars
|
/\ UNCHANGED workerVars
|
||||||
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
||||||
|
|
@ -524,7 +533,8 @@ ScheduleRetry(j) ==
|
||||||
/\ phase' = [phase EXCEPT ![j] = Queued]
|
/\ phase' = [phase EXCEPT ![j] = Queued]
|
||||||
/\ dispatchNeeded' = [dispatchNeeded EXCEPT ![j] = TRUE]
|
/\ dispatchNeeded' = [dispatchNeeded EXCEPT ![j] = TRUE]
|
||||||
/\ UNCHANGED <<cancelRequested, currentToken, authority,
|
/\ UNCHANGED <<cancelRequested, currentToken, authority,
|
||||||
committedAttempt, checkpoint, checkpointValid>>
|
committedAttempt, checkpoint, checkpointStageOwner,
|
||||||
|
checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
/\ UNCHANGED workerVars
|
/\ UNCHANGED workerVars
|
||||||
/\ UNCHANGED attemptVars
|
/\ UNCHANGED attemptVars
|
||||||
|
|
@ -539,7 +549,8 @@ RequestCancel(j) ==
|
||||||
[authority EXCEPT
|
[authority EXCEPT
|
||||||
![j] = IF phase[j] = Running THEN @ ELSE NoAttempt]
|
![j] = IF phase[j] = Running THEN @ ELSE NoAttempt]
|
||||||
/\ dispatchNeeded' = [dispatchNeeded EXCEPT ![j] = FALSE]
|
/\ dispatchNeeded' = [dispatchNeeded EXCEPT ![j] = FALSE]
|
||||||
/\ UNCHANGED <<currentToken, committedAttempt, checkpoint, checkpointValid>>
|
/\ UNCHANGED <<currentToken, committedAttempt, checkpoint,
|
||||||
|
checkpointStageOwner, checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
/\ UNCHANGED workerVars
|
/\ UNCHANGED workerVars
|
||||||
/\ UNCHANGED attemptVars
|
/\ UNCHANGED attemptVars
|
||||||
|
|
@ -556,7 +567,8 @@ FinalizeCancel(j) ==
|
||||||
IF JobOf(a) = j /\ attemptState[a] = AttemptAuthorized
|
IF JobOf(a) = j /\ attemptState[a] = AttemptAuthorized
|
||||||
THEN AttemptStopped ELSE attemptState[a]]
|
THEN AttemptStopped ELSE attemptState[a]]
|
||||||
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
||||||
committedAttempt, checkpoint, checkpointValid>>
|
committedAttempt, checkpoint, checkpointStageOwner,
|
||||||
|
checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
/\ UNCHANGED workerVars
|
/\ UNCHANGED workerVars
|
||||||
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
||||||
|
|
@ -664,6 +676,7 @@ PersistCheckpoint(a) ==
|
||||||
/\ attemptProgress[a] > 0
|
/\ attemptProgress[a] > 0
|
||||||
/\ (~checkpointValid[j] \/ checkpoint[j] # attemptProgress[a])
|
/\ (~checkpointValid[j] \/ checkpoint[j] # attemptProgress[a])
|
||||||
/\ checkpoint' = [checkpoint EXCEPT ![j] = attemptProgress[a]]
|
/\ checkpoint' = [checkpoint EXCEPT ![j] = attemptProgress[a]]
|
||||||
|
/\ checkpointStageOwner' = [checkpointStageOwner EXCEPT ![j] = a]
|
||||||
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = TRUE]
|
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = TRUE]
|
||||||
/\ UNCHANGED <<phase, cancelRequested, currentToken, authority,
|
/\ UNCHANGED <<phase, cancelRequested, currentToken, authority,
|
||||||
dispatchNeeded, committedAttempt>>
|
dispatchNeeded, committedAttempt>>
|
||||||
|
|
@ -674,6 +687,8 @@ PersistCheckpoint(a) ==
|
||||||
InvalidateCheckpoint(j) ==
|
InvalidateCheckpoint(j) ==
|
||||||
/\ ~Terminal(j)
|
/\ ~Terminal(j)
|
||||||
/\ checkpointValid[j]
|
/\ checkpointValid[j]
|
||||||
|
/\ checkpointStageOwner' =
|
||||||
|
[checkpointStageOwner EXCEPT ![j] = NoAttempt]
|
||||||
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = FALSE]
|
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = FALSE]
|
||||||
/\ UNCHANGED <<phase, cancelRequested, currentToken, authority,
|
/\ UNCHANGED <<phase, cancelRequested, currentToken, authority,
|
||||||
dispatchNeeded, committedAttempt, checkpoint>>
|
dispatchNeeded, committedAttempt, checkpoint>>
|
||||||
|
|
@ -740,6 +755,7 @@ AcceptSuccess(a) ==
|
||||||
/\ authority' = [authority EXCEPT ![j] = NoAttempt]
|
/\ authority' = [authority EXCEPT ![j] = NoAttempt]
|
||||||
/\ committedAttempt' = [committedAttempt EXCEPT ![j] = a]
|
/\ committedAttempt' = [committedAttempt EXCEPT ![j] = a]
|
||||||
/\ checkpoint' = [checkpoint EXCEPT ![j] = MaxProgress]
|
/\ checkpoint' = [checkpoint EXCEPT ![j] = MaxProgress]
|
||||||
|
/\ checkpointStageOwner' = [checkpointStageOwner EXCEPT ![j] = a]
|
||||||
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = TRUE]
|
/\ checkpointValid' = [checkpointValid EXCEPT ![j] = TRUE]
|
||||||
/\ attemptState' =
|
/\ attemptState' =
|
||||||
[attemptState EXCEPT ![a] = AttemptCommitted]
|
[attemptState EXCEPT ![a] = AttemptCommitted]
|
||||||
|
|
@ -765,7 +781,8 @@ AcceptFailure(a, outcome) ==
|
||||||
[attemptState EXCEPT ![a] = AttemptStopped]
|
[attemptState EXCEPT ![a] = AttemptStopped]
|
||||||
/\ pendingOutcome' = [pendingOutcome EXCEPT ![a] = NoOutcome]
|
/\ pendingOutcome' = [pendingOutcome EXCEPT ![a] = NoOutcome]
|
||||||
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
/\ UNCHANGED <<cancelRequested, currentToken, dispatchNeeded,
|
||||||
committedAttempt, checkpoint, checkpointValid>>
|
committedAttempt, checkpoint, checkpointStageOwner,
|
||||||
|
checkpointValid>>
|
||||||
/\ UNCHANGED coordinationVars
|
/\ UNCHANGED coordinationVars
|
||||||
/\ UNCHANGED workerVars
|
/\ UNCHANGED workerVars
|
||||||
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
/\ UNCHANGED <<attemptWorker, attemptProgress, initialProgress,
|
||||||
|
|
@ -800,6 +817,9 @@ CleanupStage(a) ==
|
||||||
IN /\ stageState[a] \in {StagePartial, StageComplete}
|
IN /\ stageState[a] \in {StagePartial, StageComplete}
|
||||||
/\ committedAttempt[j] # a
|
/\ committedAttempt[j] # a
|
||||||
/\ ~CurrentAuthority(a)
|
/\ ~CurrentAuthority(a)
|
||||||
|
/\ (Terminal(j)
|
||||||
|
\/ ~checkpointValid[j]
|
||||||
|
\/ checkpointStageOwner[j] # a)
|
||||||
/\ (attemptState[a] = AttemptStopped
|
/\ (attemptState[a] = AttemptStopped
|
||||||
\/ workerState[attemptWorker[a]] = WorkerDown)
|
\/ workerState[attemptWorker[a]] = WorkerDown)
|
||||||
/\ stageState' = [stageState EXCEPT ![a] = StageCleaned]
|
/\ stageState' = [stageState EXCEPT ![a] = StageCleaned]
|
||||||
|
|
@ -1002,6 +1022,7 @@ TypeOK ==
|
||||||
/\ dispatchNeeded \in [Jobs -> BOOLEAN]
|
/\ dispatchNeeded \in [Jobs -> BOOLEAN]
|
||||||
/\ committedAttempt \in [Jobs -> AttemptIds \cup {NoAttempt}]
|
/\ committedAttempt \in [Jobs -> AttemptIds \cup {NoAttempt}]
|
||||||
/\ checkpoint \in [Jobs -> 0..MaxProgress]
|
/\ checkpoint \in [Jobs -> 0..MaxProgress]
|
||||||
|
/\ checkpointStageOwner \in [Jobs -> AttemptIds \cup {NoAttempt}]
|
||||||
/\ checkpointValid \in [Jobs -> BOOLEAN]
|
/\ checkpointValid \in [Jobs -> BOOLEAN]
|
||||||
/\ queued \in [Jobs -> BOOLEAN]
|
/\ queued \in [Jobs -> BOOLEAN]
|
||||||
/\ reservation \in [Jobs -> Workers \cup {NoWorker}]
|
/\ reservation \in [Jobs -> Workers \cup {NoWorker}]
|
||||||
|
|
@ -1154,8 +1175,21 @@ ResumeValidity ==
|
||||||
/\ (initialProgress[a] > 0 => resumedFromCheckpoint[a])
|
/\ (initialProgress[a] > 0 => resumedFromCheckpoint[a])
|
||||||
/\ (resumedFromCheckpoint[a] => initialProgress[a] > 0)
|
/\ (resumedFromCheckpoint[a] => initialProgress[a] > 0)
|
||||||
|
|
||||||
\* Uncommitted staging is only retained for live or stopped attempts, not cleaned
|
CheckpointStagingOwnership ==
|
||||||
\* while still authoritative (cleanup gated in CleanupStage).
|
\A j \in Jobs :
|
||||||
|
/\ (~checkpointValid[j] => checkpointStageOwner[j] = NoAttempt)
|
||||||
|
/\ (checkpointValid[j] =>
|
||||||
|
/\ checkpoint[j] > 0
|
||||||
|
/\ checkpointStageOwner[j] \in AttemptIds
|
||||||
|
/\ JobOf(checkpointStageOwner[j]) = j
|
||||||
|
/\ attemptState[checkpointStageOwner[j]] # AttemptUnused)
|
||||||
|
/\ (~Terminal(j) /\ checkpointValid[j] =>
|
||||||
|
stageState[checkpointStageOwner[j]]
|
||||||
|
\in {StagePartial, StageComplete})
|
||||||
|
/\ (phase[j] = Running /\ checkpointValid[j] =>
|
||||||
|
checkpointStageOwner[j] = authority[j])
|
||||||
|
|
||||||
|
\* Transfer removes the predecessor's cleanup eligibility before replacement I/O.
|
||||||
StagingOwnership ==
|
StagingOwnership ==
|
||||||
\A a \in AttemptIds :
|
\A a \in AttemptIds :
|
||||||
/\ (stageState[a] = StageCleaned =>
|
/\ (stageState[a] = StageCleaned =>
|
||||||
|
|
@ -1174,6 +1208,7 @@ TerminalStep ==
|
||||||
/\ authority'[j] = authority[j]
|
/\ authority'[j] = authority[j]
|
||||||
/\ committedAttempt'[j] = committedAttempt[j]
|
/\ committedAttempt'[j] = committedAttempt[j]
|
||||||
/\ checkpoint'[j] = checkpoint[j]
|
/\ checkpoint'[j] = checkpoint[j]
|
||||||
|
/\ checkpointStageOwner'[j] = checkpointStageOwner[j]
|
||||||
/\ checkpointValid'[j] = checkpointValid[j]
|
/\ checkpointValid'[j] = checkpointValid[j]
|
||||||
FenceStep ==
|
FenceStep ==
|
||||||
\A j \in Jobs : currentToken'[j] >= currentToken[j]
|
\A j \in Jobs : currentToken'[j] >= currentToken[j]
|
||||||
|
|
@ -1243,6 +1278,9 @@ CleanupEligible(a) ==
|
||||||
/\ stageState[a] \in {StagePartial, StageComplete}
|
/\ stageState[a] \in {StagePartial, StageComplete}
|
||||||
/\ committedAttempt[JobOf(a)] # a
|
/\ committedAttempt[JobOf(a)] # a
|
||||||
/\ ~CurrentAuthority(a)
|
/\ ~CurrentAuthority(a)
|
||||||
|
/\ (Terminal(JobOf(a))
|
||||||
|
\/ ~checkpointValid[JobOf(a)]
|
||||||
|
\/ checkpointStageOwner[JobOf(a)] # a)
|
||||||
/\ (attemptState[a] = AttemptStopped
|
/\ (attemptState[a] = AttemptStopped
|
||||||
\/ workerState[attemptWorker[a]] = WorkerDown)
|
\/ workerState[attemptWorker[a]] = WorkerDown)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
44
docs/protocol/RemoraResume.cfg
Normal file
44
docs/protocol/RemoraResume.cfg
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
SPECIFICATION SafetySpec
|
||||||
|
|
||||||
|
CHECK_DEADLOCK TRUE
|
||||||
|
|
||||||
|
CONSTANTS
|
||||||
|
Jobs = {j1}
|
||||||
|
Workers = {w1}
|
||||||
|
InitialWorkers = {w1}
|
||||||
|
NoJob = NoJob
|
||||||
|
NoWorker = NoWorker
|
||||||
|
MaxAttempts = 2
|
||||||
|
MaxProgress = 2
|
||||||
|
LeaseLimit = 1
|
||||||
|
ReservationLimit = 1
|
||||||
|
LocalLimit = 1
|
||||||
|
GlobalLimit = 1
|
||||||
|
FaultsEnabled = FALSE
|
||||||
|
FaultServices = {}
|
||||||
|
MaxCoordLosses = 0
|
||||||
|
MaxPartitions = 0
|
||||||
|
MaxCredentialIntents = 0
|
||||||
|
|
||||||
|
INVARIANTS
|
||||||
|
TypeOK
|
||||||
|
StateConsistency
|
||||||
|
AllocatedTokensUsed
|
||||||
|
LiveProgressWellFormed
|
||||||
|
LiveProgressCompatibleWithLiveLease
|
||||||
|
AtMostOneLiveLeasePerJob
|
||||||
|
AuthorityWellFormed
|
||||||
|
CommittedResultConsistent
|
||||||
|
CancellationSafety
|
||||||
|
PermitSafety
|
||||||
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
|
StagingOwnership
|
||||||
|
CredentialLifecycleWellFormed
|
||||||
|
NoOrphanSecrets
|
||||||
|
|
||||||
|
PROPERTIES
|
||||||
|
TerminalStateIsImmutable
|
||||||
|
FencingTokensMonotonic
|
||||||
|
CommitIsFencedCAS
|
||||||
|
FailureDispositionHonored
|
||||||
|
|
@ -35,6 +35,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ INVARIANTS
|
||||||
CancellationSafety
|
CancellationSafety
|
||||||
PermitSafety
|
PermitSafety
|
||||||
ResumeValidity
|
ResumeValidity
|
||||||
|
CheckpointStagingOwnership
|
||||||
StagingOwnership
|
StagingOwnership
|
||||||
CredentialLifecycleWellFormed
|
CredentialLifecycleWellFormed
|
||||||
NoOrphanSecrets
|
NoOrphanSecrets
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ flowchart TD
|
||||||
- Activation and inactive-attempt recovery serialize against the same durable authority. Recovery revalidates coordination after entering that boundary and reaps an attempt that remains authorized; compensation removes any pre-commit lease. Activation removes any lease that cannot be paired with the durable executing tuple.
|
- Activation and inactive-attempt recovery serialize against the same durable authority. Recovery revalidates coordination after entering that boundary and reaps an attempt that remains authorized; compensation removes any pre-commit lease. Activation removes any lease that cannot be paired with the durable executing tuple.
|
||||||
- Reservations have a bounded lifetime. Expiry makes unallocated work eligible for redispatch and makes a durably authorized attempt without its exact live lease eligible for reaping; it never reverses durable authority from coordination state alone.
|
- Reservations have a bounded lifetime. Expiry makes unallocated work eligible for redispatch and makes a durably authorized attempt without its exact live lease eligible for reaping; it never reverses durable authority from coordination state alone.
|
||||||
- A lost successful activation response replays success only while the exact live lease and complete durable executing tuple still agree. A changed attempt, fence, or worker incarnation is a precondition failure.
|
- A lost successful activation response replays success only while the exact live lease and complete durable executing tuple still agree. A changed attempt, fence, or worker incarnation is a precondition failure.
|
||||||
- The envelope projects the accepted non-secret source metadata and a sensitive-input reference, any durable `ResolvedSource`, the immutable execution grant and concrete target, the attempt-scoped staging identity, pinned credential-version references, and the validated checkpoint and destination-resume evidence available to that attempt.
|
- The envelope projects the accepted non-secret source metadata and a sensitive-input reference, any durable `ResolvedSource`, the immutable execution grant and concrete target, the attempt's exact staging identity, pinned credential-version references, and the validated checkpoint and destination-resume evidence available to that attempt. A replacement may inherit the predecessor's physical staging identity only through the durable checkpoint-ownership transfer defined below.
|
||||||
- A source identity or inventory that is initially unresolved is durably pinned once before concrete checkpoint validation or reuse relies on it. Pinning is a fenced durable mutation and a conflicting value is rejected.
|
- A source identity or inventory that is initially unresolved is durably pinned once before concrete checkpoint validation or reuse relies on it. Pinning is a fenced durable mutation and a conflicting value is rejected.
|
||||||
- Large source inventories, completed-part sets, and other unbounded collections are represented by durable streamable descriptors rather than materialized in the envelope.
|
- Large source inventories, completed-part sets, and other unbounded collections are represented by durable streamable descriptors rather than materialized in the envelope.
|
||||||
- Envelope transport is an implementation choice. It may accompany queue delivery or claim, or be read separately, but a worker never infers it from reconstructible coordination state.
|
- Envelope transport is an implementation choice. It may accompany queue delivery or claim, or be read separately, but a worker never infers it from reconstructible coordination state.
|
||||||
|
|
@ -136,12 +136,15 @@ flowchart TD
|
||||||
- Concrete work for `CleanupStage` is materialized from exact attempt ownership and pending cleanup data in `DurableStore`, independently of `CoordinationStore`.
|
- Concrete work for `CleanupStage` is materialized from exact attempt ownership and pending cleanup data in `DurableStore`, independently of `CoordinationStore`.
|
||||||
- Ambient cleanup processes are stateless and idempotent. Worker-local cleanup may reduce latency but is not the only cleanup path.
|
- Ambient cleanup processes are stateless and idempotent. Worker-local cleanup may reduce latency but is not the only cleanup path.
|
||||||
- Cleanup addresses exact attempt object or multipart identities. Eligibility comes only from `CleanupStage`; missing coordination state, target-object age, and raw prefix membership are not substitutes.
|
- Cleanup addresses exact attempt object or multipart identities. Eligibility comes only from `CleanupStage`; missing coordination state, target-object age, and raw prefix membership are not substitutes.
|
||||||
|
- Every reusable checkpoint has one durable logical staging owner. Its exact retained objects, multipart state, inventory rows, and pending cleanup identities are ineligible for cleanup while the job is nonterminal.
|
||||||
|
- A replacement is authorized only after the checkpoint owner is durably stopped. Authorization atomically transfers logical ownership and all retained exact identities to the replacement before it can perform I/O. Physical keys may retain their original globally unique attempt namespace; key prefixes do not determine current logical ownership.
|
||||||
|
- State beyond the checkpoint's validated boundary remains owned by the predecessor and becomes independently cleanup-eligible after transfer. A claimed or completed cleanup identity cannot be transferred or used as resume evidence.
|
||||||
- Target lifecycle rules are storage hygiene only. They do not substitute for `JobProtocol` publication or cleanup eligibility and must not expire objects retained by a committed aggregate.
|
- Target lifecycle rules are storage hygiene only. They do not substitute for `JobProtocol` publication or cleanup eligibility and must not expire objects retained by a committed aggregate.
|
||||||
- Independent writers and lifecycle mechanisms must be unable to replace or expire live or committed identities in Remora's reserved namespace. A deployment that cannot establish this property is unsupported.
|
- Independent writers and lifecycle mechanisms must be unable to replace or expire live or committed identities in Remora's reserved namespace. A deployment that cannot establish this property is unsupported.
|
||||||
|
|
||||||
## Source Identity and Resumption
|
## Source Identity and Resumption
|
||||||
|
|
||||||
- `checkpointValid` abstracts the concrete proof defined here. A reusable checkpoint binds an immutable `Source` identity, an exact completed boundary, and validated destination state; absent or changed proof makes the checkpoint unavailable to a replacement attempt.
|
- `checkpointValid` abstracts the concrete proof defined here. A reusable checkpoint binds an immutable `Source` identity, an exact completed boundary, validated destination state, and its current durable staging owner; absent or changed proof makes the checkpoint unavailable to a replacement attempt.
|
||||||
- HTTP identity includes the resolved final URL, a strong representation validator as defined by `RFC 9110`, representation length, and identity content encoding. Resume requires a conditional byte-range response whose validator, URL, encoding, and range exactly match the checkpoint. Weak validators, length, or modification time alone do not qualify.
|
- HTTP identity includes the resolved final URL, a strong representation validator as defined by `RFC 9110`, representation length, and identity content encoding. Resume requires a conditional byte-range response whose validator, URL, encoding, and range exactly match the checkpoint. Weak validators, length, or modification time alone do not qualify.
|
||||||
- Object-store identity includes endpoint, bucket, key, size, and an immutable version ID when available. Without a version ID, resume requires a matching conditional range read. Destination multipart reuse additionally requires the same endpoint, bucket, key, upload ID, and exact re-listed completed parts.
|
- Object-store identity includes endpoint, bucket, key, size, and an immutable version ID when available. Without a version ID, resume requires a matching conditional range read. Destination multipart reuse additionally requires the same endpoint, bucket, key, upload ID, and exact re-listed completed parts.
|
||||||
- An HTTP or object-store single-object source supplies one explicit `result_path` validated under the manifest member-path rules. The adapter does not derive the result member path from a URL or object key.
|
- An HTTP or object-store single-object source supplies one explicit `result_path` validated under the manifest member-path rules. The adapter does not derive the result member path from a URL or object key.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue