src/ResourceOptions.bend

mylsm-lsm-store@0.6.0.1 · 274 lines · 43 definitions

1import Base
2
3# Carries the state for TransportLimits.
4type TransportLimits is Data:
5  TransportLimits{connections: U32, frame_bytes: U32,
6    receive_bytes: U32, response_bytes: U32,
7    frame_timeout_ms: U32, response_timeout_ms: U32}
8
9# Carries the state for QueueLimits.
10type QueueLimits is Data:
11  QueueLimits{requests: U32, bytes: U32, timeout_ms: U32}
12
13# Carries the state for ReaderLimits.
14type ReaderLimits is Data:
15  ReaderLimits{snapshots: U32, cursors: U32,
16    cursors_per_snapshot: U32, retained_root_bytes: U32,
17    retired_files: U32, index_page_bytes: U32,
18    index_buffer_bytes: U32, restore_bytes: U32}
19
20# Carries the state for Options.
21type Options is Data:
22  Options{transport: TransportLimits, queue: QueueLimits,
23    readers: ReaderLimits}
24
25# Carries the state for Decision.
26type Decision is Data:
27  Accepted{options: Options}
28  InvalidTransport{}
29  InvalidQueue{}
30  InvalidReaders{}
31
32# Handles defaults.
33def defaults() -> Options:
34  Options{
35    TransportLimits{64, 16777216, 16777216, 16777216,
36      30000, 30000},
37    QueueLimits{64, 16777216, 30000},
38    ReaderLimits{64, 4096, 64, 67108864, 64,
39      16384, 65536, 67108864}}
40
41def fields.transport(
42  transport: TransportLimits,
43  tail: List<&2, U32>
44) -> List<&2, U32>:
45  match transport:
46    case TransportLimits{connections, frame_bytes, receive_bytes,
47      response_bytes, frame_timeout_ms, response_timeout_ms}:
48      Con{connections, Con{frame_bytes, Con{receive_bytes,
49        Con{response_bytes, Con{frame_timeout_ms,
50          Con{response_timeout_ms, tail}}}}}}
51
52def fields.queue(
53  queue: QueueLimits,
54  tail: List<&2, U32>
55) -> List<&2, U32>:
56  match queue:
57    case QueueLimits{requests, bytes, timeout_ms}:
58      Con{requests, Con{bytes, Con{timeout_ms, tail}}}
59
60def fields.readers(
61  readers: ReaderLimits,
62  tail: List<&2, U32>
63) -> List<&2, U32>:
64  match readers:
65    case ReaderLimits{snapshots, cursors, cursors_per_snapshot,
66      retained_root_bytes, retired_files, index_page_bytes,
67      index_buffer_bytes, restore_bytes}:
68      Con{snapshots, Con{cursors, Con{cursors_per_snapshot,
69        Con{retained_root_bytes, Con{retired_files,
70          Con{index_page_bytes, Con{index_buffer_bytes,
71            Con{restore_bytes, tail}}}}}}}}
72
73def fields.value(options: Options) -> List<&2, U32>:
74  match options:
75    case Options{transport, queue, readers}:
76      fields.transport(transport, fields.queue(queue,
77        fields.readers(readers, Nil{})))
78
79# Handles fields.
80def fields(+options: Options) -> List<&2, U32>:
81  fields.value(options)
82
83def fields.same(
84  left: List<&2, U32>,
85  right: List<&2, U32>
86) -> Bool:
87  match left right:
88    case Con{l1, Con{l2, Con{l3, Con{l4, Con{l5, Con{l6,
89      Con{l7, Con{l8, Con{l9, Con{l10, Con{l11, Con{l12,
90        Con{l13, Con{l14, Con{l15, Con{l16, Con{l17, Nil{}}}}}}}}}}}}}}}}}}
91      Con{r1, Con{r2, Con{r3, Con{r4, Con{r5, Con{r6,
92        Con{r7, Con{r8, Con{r9, Con{r10, Con{r11, Con{r12,
93          Con{r13, Con{r14, Con{r15, Con{r16, Con{r17, Nil{}}}}}}}}}}}}}}}}}}:
94      Bool.and(U32.is_eq(l1, r1), Bool.and(U32.is_eq(l2, r2),
95        Bool.and(U32.is_eq(l3, r3), Bool.and(U32.is_eq(l4, r4),
96          Bool.and(U32.is_eq(l5, r5), Bool.and(U32.is_eq(l6, r6),
97            Bool.and(U32.is_eq(l7, r7), Bool.and(U32.is_eq(l8, r8),
98              Bool.and(U32.is_eq(l9, r9), Bool.and(U32.is_eq(l10, r10),
99                Bool.and(U32.is_eq(l11, r11), Bool.and(U32.is_eq(l12, r12),
100                  Bool.and(U32.is_eq(l13, r13),
101                    Bool.and(U32.is_eq(l14, r14),
102                      Bool.and(U32.is_eq(l15, r15),
103                        Bool.and(U32.is_eq(l16, r16),
104                          U32.is_eq(l17, r17)))))))))))))))))
105    case _ _: False{}
106
107# Handles same.
108def same(+left: Options, +right: Options) -> Bool:
109  fields.same(fields(left), fields(right))
110
111def snapshot.limits(options: Options) -> U32 & U32:
112  match options:
113    case Options{_, _, ReaderLimits{snapshots, _, _, retained_root_bytes, _, _, _, _}}:
114      (snapshots, retained_root_bytes)
115
116def snapshot.retained.bytes(options: Options) -> U32:
117  match options:
118    case Options{_, _, ReaderLimits{_, _, _, retained_root_bytes, _, _, _, _}}:
119      retained_root_bytes
120
121def snapshot.count(options: Options) -> U32:
122  match options:
123    case Options{_, _, ReaderLimits{snapshots, _, _, _, _, _, _, _}}:
124      snapshots
125
126def cursor.per.snapshot(options: Options) -> U32:
127  match options:
128    case Options{_, _, ReaderLimits{_, _, cursors_per_snapshot, _, _, _, _, _}}:
129      cursors_per_snapshot
130
131def cursor.count(options: Options) -> U32:
132  match options:
133    case Options{_, _, ReaderLimits{_, cursors, _, _, _, _, _, _}}:
134      cursors
135
136def transport.frame.bytes(options: Options) -> U32:
137  match options:
138    case Options{TransportLimits{_, frame_bytes, _, _, _, _}, _, _}:
139      frame_bytes
140
141def transport.receive.bytes(options: Options) -> U32:
142  match options:
143    case Options{TransportLimits{_, _, receive_bytes, _, _, _}, _, _}:
144      receive_bytes
145
146def transport.connections(options: Options) -> U32:
147  match options:
148    case Options{TransportLimits{connections, _, _, _, _, _}, _, _}:
149      connections
150
151def transport.frame.timeout(options: Options) -> U32:
152  match options:
153    case Options{TransportLimits{_, _, _, _, frame_timeout_ms, _}, _, _}:
154      frame_timeout_ms
155
156def transport.response.timeout(options: Options) -> U32:
157  match options:
158    case Options{TransportLimits{_, _, _, _, _, response_timeout_ms}, _, _}:
159      response_timeout_ms
160
161def queue.timeout(options: Options) -> U32:
162  match options:
163    case Options{_, QueueLimits{_, _, timeout_ms}, _}:
164      timeout_ms
165
166def queue.requests(options: Options) -> U32:
167  match options:
168    case Options{_, QueueLimits{requests, _, _}, _}:
169      requests
170
171def queue.bytes(options: Options) -> U32:
172  match options:
173    case Options{_, QueueLimits{_, bytes, _}, _}:
174      bytes
175
176def transport.response.bytes(options: Options) -> U32:
177  match options:
178    case Options{TransportLimits{_, _, _, response_bytes, _, _}, _, _}:
179      response_bytes
180
181def response.admitted(length: U32, max_bytes: U32) -> Bool:
182  U32.is_le(length, max_bytes)
183
184# Handles positive.
185def positive(value: U32) -> Bool:
186  U32.is_lt(0, value)
187
188# Handles bounded.
189def bounded(+value: U32, maximum: U32) -> Bool:
190  positive(value) && U32.is_le(value, maximum)
191
192def frame.valid(+frame_bytes: U32, +receive_bytes: U32,
193  +response_bytes: U32) -> Bool:
194  bounded(frame_bytes, 1073741824) &&
195    U32.is_le(frame_bytes, receive_bytes) &&
196    U32.is_le(frame_bytes, response_bytes) &&
197    bounded(receive_bytes, 1073741824) &&
198    bounded(response_bytes, 1073741824)
199
200def transport.valid(limits: TransportLimits) -> Bool:
201  match limits:
202    case TransportLimits{connections, frame_bytes, receive_bytes,
203      response_bytes, frame_timeout_ms, response_timeout_ms}:
204      bounded(connections, 4294967295) &&
205        frame.valid(frame_bytes, receive_bytes, response_bytes) &&
206        bounded(frame_timeout_ms, 4294967295) &&
207        bounded(response_timeout_ms, 4294967295)
208
209def queue.bytes.valid(+bytes: U32) -> Bool:
210  bounded(bytes, 1073741824)
211
212def queue.valid(limits: QueueLimits) -> Bool:
213  match limits:
214    case QueueLimits{requests, bytes, timeout_ms}:
215      bounded(requests, 4294967295) &&
216        queue.bytes.valid(bytes) &&
217        bounded(timeout_ms, 4294967295)
218
219def cursor.limits.valid(+cursors: U32,
220  +cursors_per_snapshot: U32) -> Bool:
221  bounded(cursors, 4096) &&
222    bounded(cursors_per_snapshot, 64) &&
223    U32.is_le(cursors_per_snapshot, cursors)
224
225def retained.limits.valid(+snapshots: U32,
226  +retained_root_bytes: U32, +retired_files: U32) -> Bool:
227  bounded(snapshots, 64) &&
228    bounded(retained_root_bytes, 67108864) &&
229    bounded(retired_files, 64)
230
231def index.limits.valid(+index_page_bytes: U32,
232  +index_buffer_bytes: U32) -> Bool:
233  bounded(index_page_bytes, 16384) &&
234    bounded(index_buffer_bytes, 65536) &&
235    U32.is_le(index_page_bytes, index_buffer_bytes)
236
237def readers.valid(limits: ReaderLimits) -> Bool:
238  match limits:
239    case ReaderLimits{snapshots, cursors, cursors_per_snapshot,
240      retained_root_bytes, retired_files, index_page_bytes,
241      index_buffer_bytes, restore_bytes}:
242      cursor.limits.valid(cursors, cursors_per_snapshot) &&
243        retained.limits.valid(snapshots, retained_root_bytes, retired_files) &&
244        index.limits.valid(index_page_bytes, index_buffer_bytes) &&
245        bounded(restore_bytes, 67108864)
246
247def validate.readers(options: Options, readers_ok: Bool) -> Decision:
248  match readers_ok:
249    case True{}: Accepted{options}
250    case False{}: InvalidReaders{}
251
252def validate.queue(options: Options, queue_ok: Bool,
253  readers_ok: Bool) -> Decision:
254  match queue_ok:
255    case True{}: validate.readers(options, readers_ok)
256    case False{}: InvalidQueue{}
257
258def validate.transport(options: Options, transport_ok: Bool,
259  queue_ok: Bool, readers_ok: Bool) -> Decision:
260  match transport_ok:
261    case True{}: validate.queue(options, queue_ok, readers_ok)
262    case False{}: InvalidTransport{}
263
264# Handles validate.
265def validate(+options: Options) -> Decision:
266  match options:
267    case Options{transport, queue, readers}:
268      validate.transport(options, transport.valid(transport),
269        queue.valid(queue), readers.valid(readers))
270
271def reader.retired.files(options: Options) -> U32:
272  match options:
273    case Options{_, _, ReaderLimits{_, _, _, _, retired_files, _, _, _}}:
274      retired_files