src/ResourceOptions.bend
mylsm-lsm-store@0.6.0.1 · 274 lines · 43 definitions
1import Base
2
3
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
10type QueueLimits is Data:
11 QueueLimits{requests: U32, bytes: U32, timeout_ms: U32}
12
13
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
21type Options is Data:
22 Options{transport: TransportLimits, queue: QueueLimits,
23 readers: ReaderLimits}
24
25
26type Decision is Data:
27 Accepted{options: Options}
28 InvalidTransport{}
29 InvalidQueue{}
30 InvalidReaders{}
31
32
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
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
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
185def positive(value: U32) -> Bool:
186 U32.is_lt(0, value)
187
188
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
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