1 import Base 2 import ./DurableError.bend as DurableError 3 4 # Tracks whether the handle accepts data operations. 5 type HandleState is Data: 6 Open{} 7 Poisoned{} 8 MaintenanceBlocked{} 9 10 # Increments the per-handle operation error count. 11 def next_operation_errors(count: Nat) -> Nat: 12 Nat.add(count, 1n) 13 14 # Distinguishes failures before and after WAL append begins. 15 type AppendPhase is Data: 16 BeforeAppend{} 17 AppendStarted{} 18 19 # Tracks whether failed maintenance blocks later writes. 20 type MaintenanceState is Data: 21 MaintenanceSucceeded{} 22 MaintenanceFailed{error: DurableError.Error} 23 24 # Checks whether accepts data operation. 25 def accepts_data_operation(state: HandleState) -> Bool: 26 match state: 27 case Open{}: 28 True{} 29 case Poisoned{}: 30 False{} 31 case MaintenanceBlocked{}: 32 False{} 33 34 # Selects handle state from the write failure stage. 35 def state_after_write_failure(phase: AppendPhase, current: HandleState) -> HandleState: 36 match phase: 37 case BeforeAppend{}: 38 current 39 case AppendStarted{}: 40 Poisoned{} 41 42 # Blocks writes when maintenance fails. 43 def state_after_maintenance(result: MaintenanceState) -> HandleState: 44 match result: 45 case MaintenanceSucceeded{}: 46 Open{} 47 case MaintenanceFailed{_}: 48 MaintenanceBlocked{} 49 50 # Reports maintenance separately from the confirmed commit. 51 def committed_maintenance(commit_error: Maybe<&2, DurableError.Error>) -> Bool: 52 match commit_error: 53 case Some{_}: 54 False{} 55 case None{}: 56 True{}