mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
test(workouts): pin the losing side of a concurrent enrichment
Two requests can probe the same workout, both find no heart-rate series, and both mean to attach one. The unique index on `workout_id` picks a winner; the loser has to report the duplicate it turned out to be rather than claim an attach the database never made. Nothing could catch that arm going wrong: the unit fake echoes every row back as landed, and the race suite carries no series at all, so replacing the status with a constant `enriched` left the whole suite green. Two concurrent posts of the same enrichment now assert one `enriched` against one `duplicate` and a single stored series. The published contract also says now what the counters mean, instead of leaving it in a comment: an entry reported as `enriched` counts towards `duplicates`, because the top-level counters count workout rows and an enrichment writes none. Field descriptions on the response and on the per-entry status and reason, OpenAPI regenerated.
This commit is contained in:
1 parent
21a14ea679
commit
4f3a790ce7
3 files changed
+91
-6
No files matched your search
@@ -27,20 +27,48 @@ import {
|
||||
// `enriched` says the entry matched a stored workout that had no
|
||||
// heart-rate series and the series it carried was attached. The
|
||||
// workout row itself was not written, so such an entry also counts
|
||||
// towards `duplicates`; the top-level counters count rows.
|
||||
// towards `duplicates`. That rule is part of the published contract,
|
||||
// not just a note here: it rides the field descriptions below, because
|
||||
// a client summing the counters has to know which bucket an
|
||||
// enrichment lands in.
|
||||
const workoutBatchEntryResult = z
|
||||
.object({
|
||||
index: z.number().int().nonnegative(),
|
||||
status: z.enum(["inserted", "duplicate", "enriched", "skipped"]),
|
||||
reason: z.string().optional(),
|
||||
status: z
|
||||
.enum(["inserted", "duplicate", "enriched", "skipped"])
|
||||
.describe(
|
||||
"`inserted`: a new workout row. `duplicate`: the workout was already stored and nothing was written. `enriched`: the workout was already stored and the heart-rate series this entry carried was attached to it; the workout row itself was not written, and the entry also counts towards the top-level `duplicates`. `skipped`: the server refused the entry, see `reason`.",
|
||||
),
|
||||
reason: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Why a `skipped` entry was refused: `unstable_external_id` for an id that does not survive a client restart, `invalid_samples` for a heart-rate series that failed validation.",
|
||||
),
|
||||
})
|
||||
.meta({ id: "WorkoutBatchEntryResult" });
|
||||
|
||||
const workoutBatchResponse = z
|
||||
.object({
|
||||
processed: z.number().int().nonnegative(),
|
||||
inserted: z.number().int().nonnegative(),
|
||||
duplicates: z.number().int().nonnegative(),
|
||||
processed: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.describe(
|
||||
"Entries in the request. Equals `inserted + duplicates + skipped.length`.",
|
||||
),
|
||||
inserted: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.describe("Workout rows this request wrote."),
|
||||
duplicates: z
|
||||
.number()
|
||||
.int()
|
||||
.nonnegative()
|
||||
.describe(
|
||||
"Entries that wrote no workout row because the workout was already stored. The top-level counters count workout rows, so an entry reported as `enriched` counts here as well even though its heart-rate series was attached.",
|
||||
),
|
||||
skipped: z.array(
|
||||
z.object({
|
||||
index: z.number().int().nonnegative(),
|
||||
|
||||
Reference in new issue
Block a user