src/DbLockPolicy.bend
mylsm-lsm-store@0.6.0.1 · 105 lines · 13 definitions
1import Base
2import mylsm-lsm-store@0.6.0.1/src/DurableError.bend as DurableError
3
4
5type WaitDecision is Data:
6 LockAcquired{}
7 LockRetry{sleep_ms: Nat}
8 LockTimedOut{}
9 LockFatal{}
10
11
12def busy_code(+code: U32) -> Bool:
13 U32.is_eq(code, 11) || U32.is_eq(code, 35)
14
15
16def missing_code(+code: U32) -> Bool:
17 U32.is_eq(code, 2)
18
19
20def unsupported_code(+code: U32) -> Bool:
21 U32.is_eq(code, 45) || U32.is_eq(code, 78) ||
22 U32.is_eq(code, 95) || U32.is_eq(code, 38)
23
24
25def classify_nonbusy_lock_error(
26 missing: Bool,
27 code: U32,
28 message: String,
29 operation: String,
30 path: String,
31) -> DurableError.Error:
32 match missing:
33 case True{}:
34 DurableError.Error{DurableError.NotFound{}, operation, path, code, message}
35 case False{}:
36 DurableError.Error{DurableError.Io{}, operation, path, code, message}
37
38def classify_lock.nonbusy.platform(
39 unsupported: Bool,
40 missing: Bool,
41 code: U32,
42 message: String,
43 operation: String,
44 path: String
45) -> DurableError.Error:
46 match unsupported:
47 case True{}:
48 DurableError.Error{DurableError.UnsupportedPlatform{}, operation,
49 path, code, message}
50 case False{}:
51 classify_nonbusy_lock_error(missing, code, message, operation, path)
52
53
54def classify_lock_nonbusy(
55 unsupported: Bool,
56 missing: Bool,
57 code: U32,
58 message: String,
59 operation: String,
60 path: String
61) -> DurableError.Error:
62 classify_lock.nonbusy.platform(unsupported, missing, code, message,
63 operation, path)
64
65
66def classify_lock_busy(busy: Bool, +code: U32, message: String, operation: String, path: String) -> DurableError.Error:
67 match busy:
68 case True{}:
69 DurableError.Error{DurableError.Busy{}, operation, path, code, message}
70 case False{}:
71 classify_lock_nonbusy(unsupported_code(code), missing_code(code),
72 code, message, operation, path)
73
74
75def classify_lock_error(+code: U32, message: String, operation: String, path: String) -> DurableError.Error:
76 classify_lock_busy(busy_code(code), code, message, operation, path)
77
78
79def busy_wait.remaining(remaining_ms: Nat, backoff_ms: Nat) -> WaitDecision:
80 match remaining_ms:
81 case 0n:
82 LockTimedOut{}
83 case 1n+rest:
84 LockRetry{Nat.min(backoff_ms, Nat.add(1n, rest))}
85
86
87def busy_wait_decision(elapsed_ms: Nat, timeout_ms: Nat, backoff_ms: Nat) -> WaitDecision:
88 busy_wait.remaining(Nat.sub(timeout_ms, elapsed_ms), backoff_ms)
89
90
91def wait_decision(
92 acquired: Bool,
93 busy: Bool,
94 elapsed_ms: Nat,
95 timeout_ms: Nat,
96 backoff_ms: Nat
97) -> WaitDecision:
98 Bool.pick(WaitDecision, acquired, LockAcquired{},
99 Bool.pick(WaitDecision, busy,
100 busy_wait_decision(elapsed_ms, timeout_ms, backoff_ms),
101 LockFatal{}))
102
103
104def wait_options_valid(timeout_ms: U32, +backoff_ms: U32) -> Bool:
105 U32.is_le(timeout_ms, 60000) && U32.is_lt(0, backoff_ms) && U32.is_le(backoff_ms, 1000)