Repository navigation
tests, ci: the procedure proof's milestone 0 steps on a synthetic world, and the change-group timing (foundation m0) - #277
Merged
Merged
Conversation
…ld, and the change-group timing (foundation m0) tests/db/proof/fixture.py builds one dataset, survey and field, two epochs on two SCAs, writing every product as Parquet plus a manifest and publishing it through rapidpipe.foundation; test_steps.py asserts Part 3's observations for steps 2, 4, 6, 8, 10, 11, 12 and 13 through the official views and the packets table; timing.py measures one change group over N keys. foundation.yml runs the directory; db-migrations.yml ignores it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re the group (foundation m0) Without statistics the open-binding check plans by (product, job) and the group is quadratic in N; the script measures the analysed state. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Milestone 0, task 3 of the foundation plan (PLAN.md v5, 2026-10-20, held outside the repository until its rapid_docs page lands after milestone 3): a synthetic fixture and Part 3's proof steps 2, 4, 6, 8, 10, 11, 12 and 13 as a test suite in
foundation.yml, against #275's schema and #276's operations, and the wall time of one change group at three sizes. Steps 1, 3, 5, 7 and 9 need the real stages and are milestone 3; none is faked here. No library code changes.Files
tests/db/proof/__init__.py(new, empty).tests/db/proof/fixture.py(new):World, a synthetic world on one connection: datasetD, surveyS, field 1, filter 1, epochs (exposures) 1 and 2, SCAs 1 and 2, 24 sources per image at fixed positions. Runs and jobs go throughcreate_run/create_job, every product is written as Parquet plus a manifest underfile://<tmp>/job-<id>/attempt-<n>/(with task 2'swrite_attempt) and loaded throughpublish.import_image(one difference image and its source set per job),associate(object set: predecessor's objects, this epoch's sources added to the sufficient sums, excluded source sets' members subtracted, this epoch's memberships; object ids fromrapidpipe.science.spatial.radec_index),packets(one packet set per image key:packetsindex rows andforcedrows),recipe(associate and packets over epochs, each set the next one's predecessor),cutover(the group that rebinds a recipe's objects and packets and makes its run live).tests/db/proof/test_steps.py(new): one test per step, below.tests/db/proof/timing.py(new): a script, not a test; CI does not run it.python tests/db/proof/timing.py Nagainst a throwaway database with the schema applied (it adds rows, deletes none)..github/workflows/foundation.yml: pytest also runstests/db/proof.db-migrations.yml:--ignore=tests/db/proof.The steps, as asserted
refusal=binding <id> is no longer open, itsobjectsinput andexpectsrow recorded (job_show), no binding row of its own.changegroup rebinds the object set, all four packet sets and the live binding: six rows opened and six closed under one group id;packets_officialandobjects_officialshow run 2's jobs only; every official packet row's job has exactly the inputs (object set, source set) its index row names.undoof that group: run 1 is live again,packets_officialandobjects_officialshow run 1's jobs, none of the rows the cutover closed is reopened (the restored bindings are new rows), run 2's packet rows all still exist.packetsorforcedrows, job stilllaunched. The retry (attempt 2, a new prefix) publishes 24 + 24 rows once and binds; a further call (attempt 3, no files) is a no-op,published_attemptstays 2.refusalnames the expected binding; afterwards every open packet binding is run 2's, from A's group, one per key, and run 2 is live.undoof the cutover refuses naming the object binding it opened, which has since moved, andofficialis unchanged; an explicit group restores run 1's epoch-1 packet sets and live binding; the epoch-2 object set and packet sets stay run 2's.excludesrow; the official set'snsourcesandsumfluxequal the count and sum overmembers_officialjoined tosourcesfor every object (2 members each),members_officialreturns no member of the superseded set, and its 24 sources and 24 memberships in set 1 still exist. With theexcludesrow removed this test fails (checked locally).Where the proof needed something Part 1 does not say
create_job, as the loop would choose them. Step 2's two candidates must both be launched before either publishes; launching the second after the first published would have it expect the first's binding and bind, which is correct behaviour but not the step.members_officialrather than against fixed numbers.BaseExceptionraised insidepublishafter the loads and before commit (by replacing the module's_bindfor that call); the publisher rolls back exactly as a dropped connection would. A realSIGKILLof a process is not exercised.forced.ridis 0: the fixture imports no L2 rows.Measurements
Local, PostgreSQL 18.6 container on rr (16 CPUs, 61 GiB), no q3c:
tests/db/test_schema.py test_publish.py test_change.py tests/db/proof: 23 passed, 1 skipped (q3c, CI only), under 3 s; three consecutive runs green. The proof alone: 8 passed in about 2 s. WithoutPGHOST: 8 errors, "PGHOST is not set; database tests need a database".Change-group wall time (
timing.py, onechangecall closing N bindings and opening N on the same keys, fresh database per size, same host and container):changegroupLinear, about 0.14 ms per key:
applyissues three statements per item (the closeUPDATE, the held-bindingSELECT, theINSERT), each a round trip from Python. The scriptANALYZEsofficialafter its bulk setup, the state autovacuum keeps a live table in.Finding, not fixed here (library code is task 2's and the next milestone's): on an unanalysed
official, the same 10,000-key group took 14.2 s (three runs: 14.24, 14.19, 14.11 s), slower than 100,000 keys analysed. Probe-verified withEXPLAIN: with no statistics the planner answers_open's held-bindingSELECTthroughofficial_open_product_job(product, job) and filters onkey, scanning every open binding of the product per item, so the group is quadratic in N; afterANALYZEit usesofficial_open_product_key. At 100,000 keys autovacuum had analysed the table before the group ran (18.1 s cold, 13.2 s analysed). It bites a group that runs straight after a bulk load into a young table. Candidate remedies for a later PR:ANALYZE officialin the publisher's post-commitANALYZE, or set-based closes and opens inapply(oneUPDATE ... FROM (VALUES ...)and oneINSERT ... SELECT), which would also remove most of the per-key round trips.Left for the next task
foundation.ymlrunstests/dbandtests/cliwhole once the old modules go, which pickstests/db/proofup with them;db-migrations.yml(with its--ignorelist) is deleted.tests/db/proof/fixture.pyis reusable for the verb tests (World.run,World.cutovergive a ready change group).🤖 Generated with Claude Code