[OCaml] High Intensity Training Online
refactor share import observation wire helpers
Keep promoted snapshot and imported record observation fields in one byte-order definition while preserving their distinct decode policies.
lib/persistence/import_codec.ml
@@ -135,6 +135,33 @@
135
135
| exception Unknown id -> Error (Unknown_exercise id)
136
136
end
137
137
138
Added:
(* --- observation wire fields ---
139
Added:
140
Added:
A promoted observation always serializes as the same four fields, in the same
141
Added:
order: an exercise id, a load, a rep count, and a performed time. The snapshot
142
Added:
path keeps the id as a raw [Exercise.id]. The record path resolves it to a
143
Added:
catalog [Exercise.t] and rebuilds the effort at [Positive_failure]. Both share
144
Added:
this framing, so the byte layout lives here once. *)
145
Added:
146
Added:
module Observation_wire = struct
147
Added:
(* Write the four fields from already-extracted primitive parts. *)
148
Added:
let write buf ~exercise_id ~load ~reps ~performed_at =
149
Added:
Writer.string buf exercise_id;
150
Added:
Writer.float buf load;
151
Added:
Writer.int buf reps;
152
Added:
Writer.timestamp buf performed_at
153
Added:
154
Added:
(* Read the four fields in order, resolving the leading exercise id with
155
Added:
[resolve]. The snapshot path resolves to an [Exercise.id]. The record path
156
Added:
resolves to a catalog [Exercise.t]. The remaining three fields are shared. *)
157
Added:
let read r ~resolve ~build =
158
Added:
let exercise = resolve r in
159
Added:
let load = Reader.float r in
160
Added:
let reps = Reader.int r in
161
Added:
let performed_at = Reader.timestamp r in
162
Added:
build ~exercise ~load ~reps ~performed_at
163
Added:
end
164
Added:
138
165
(* --- source set --- *)
139
166
140
167
let set_type_code : WI.source_set_type -> string = function
@@ -203,19 +230,16 @@
203
230
(* --- observation snapshot --- *)
204
231
205
232
let write_observation buf (o : WI.observation_snapshot) =
206
Removed:
Writer.string buf (o.exercise_id :> string);
207
Removed:
Writer.float buf o.load;
208
Removed:
Writer.int buf o.reps;
209
Removed:
Writer.timestamp buf o.performed_at
233
Added:
Observation_wire.write buf
234
Added:
~exercise_id:(o.exercise_id :> string)
235
Added:
~load:o.load ~reps:o.reps ~performed_at:o.performed_at
210
236
211
237
(* Read one observation snapshot, resolving its exercise id to an [Exercise.id]
212
238
through the catalog. *)
213
239
let read_observation_snapshot r : WI.observation_snapshot =
214
Removed:
let exercise_id = Reader.exercise_id r in
215
Removed:
let load = Reader.float r in
216
Removed:
let reps = Reader.int r in
217
Removed:
let performed_at = Reader.timestamp r in
218
Removed:
{ WI.exercise_id; load; reps; performed_at }
240
Added:
Observation_wire.read r ~resolve:Reader.exercise_id
241
Added:
~build:(fun ~exercise ~load ~reps ~performed_at ->
242
Added:
{ WI.exercise_id = exercise; load; reps; performed_at })
219
243
220
244
(* --- promotion snapshot --- *)
221
245
@@ -336,11 +360,12 @@
336
360
Writer.list
337
361
(fun buf obs ->
338
362
let effort = Evidence.Observation.effort obs in
339
Removed:
Writer.string buf
340
Removed:
(Exercise.id (Evidence.Stimulus.Effort.exercise effort) :> string);
341
Removed:
Writer.float buf (Evidence.Stimulus.Effort.load effort);
342
Removed:
Writer.int buf (Evidence.Stimulus.Effort.reps effort);
343
Removed:
Writer.timestamp buf (Evidence.Observation.performed_at obs))
363
Added:
Observation_wire.write buf
364
Added:
~exercise_id:
365
Added:
(Exercise.id (Evidence.Stimulus.Effort.exercise effort) :> string)
366
Added:
~load:(Evidence.Stimulus.Effort.load effort)
367
Added:
~reps:(Evidence.Stimulus.Effort.reps effort)
368
Added:
~performed_at:(Evidence.Observation.performed_at obs))
344
369
buf rec_.observations;
345
370
(* Provenance. The batch and workout ids repeat the record's own; storing them
346
371
keeps the provenance self-contained after a decode. *)
@@ -363,23 +388,21 @@
363
388
let observations =
364
389
Reader.list
365
390
(fun r ->
366
Removed:
let exercise = Reader.exercise r in
367
Removed:
let load = Reader.float r in
368
Removed:
let reps = Reader.int r in
369
Removed:
let performed_at = Reader.timestamp r in
370
Removed:
let effort =
371
Removed:
match
372
Removed:
Evidence.Stimulus.Effort.make ~exercise ~load ~reps
373
Removed:
~outcome:Evidence.Stimulus.Positive_failure
374
Removed:
with
375
Removed:
| Ok effort -> effort
376
Removed:
| Error e ->
377
Removed:
raise
378
Removed:
(Reader.Bad
379
Removed:
(Format.asprintf "observation %a"
380
Removed:
Evidence.Stimulus.Effort.pp_error e))
381
Removed:
in
382
Removed:
Evidence.Observation.make ~exercise ~effort ~performed_at)
391
Added:
Observation_wire.read r ~resolve:Reader.exercise
392
Added:
~build:(fun ~exercise ~load ~reps ~performed_at ->
393
Added:
let effort =
394
Added:
match
395
Added:
Evidence.Stimulus.Effort.make ~exercise ~load ~reps
396
Added:
~outcome:Evidence.Stimulus.Positive_failure
397
Added:
with
398
Added:
| Ok effort -> effort
399
Added:
| Error e ->
400
Added:
raise
401
Added:
(Reader.Bad
402
Added:
(Format.asprintf "observation %a"
403
Added:
Evidence.Stimulus.Effort.pp_error e))
404
Added:
in
405
Added:
Evidence.Observation.make ~exercise ~effort ~performed_at))
383
406
r
384
407
in
385
408
let prov_batch_id = Reader.string r in