Repository navigation
Conversation
…ath, with mutation proofs (refs #336) One check (tests/ingest_integrity.py) compares the stored type with the rows that were sent: the count read three ways, an order-independent digest of every column read two ways, every key exactly once, and all of it again after close and reopen. test_ingest_integrity.py runs it for insert_many (list and generator), insert_columns, insert_arrow, insert_dataframe, create_vertices, async create_record and command, append_samples, each sequential and parallel where it exists, at every chunk and commit boundary, for edges (endpoint pairs and weights), several writer threads with a reader thread, a bad row mid-batch with the documented outcome exact, rejected and raising async callbacks, and close straight after the last call. Every family also runs with a rows-dropped, duplicated, altered or uncommitted fault and must report it. The native and JVM seams are in their own files. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Refs #336. I wrote the ingest-integrity tests of #336: one check that every ingest test calls, a mutation proof for every family, and the same file on both wheels. The stress script for the rare losses is a separate study on my laptop (not in this repository); its N will be quoted in #336.
Existing work searched first.
gh pr list --state all --search "integrity"finds only a merged Dependabot PR,--search "data loss OR digest OR rows lost"finds nothing, andgh issue list --search "loss OR digest OR dropped rows"finds #336 itself and older bug reports (#7615 is the async loss thattests/test_async_executor.pyalready pins).ls tests | grep -i -E "integr|durab|loss|digest|stress"is empty. The existing tests check values and error messages path by path (test_bulk_insert.py,test_insert_columns.py,test_graph_batch.py,test_async_executor.py); none checks count, digest and reopen in one place for every path.The check (
tests/ingest_integrity.py). After a call it compares the stored type with the rows that were generated: the record count read three ways (SELECT count(*),count_type(), the length of the rows read back), an order-independent digest of every column (sum and xor of a 64-bit hash per row) read two ways (to_list()and iterating the result), and every key present exactly once. Thenclose()straight after the call, reopen from disk, and the same again (durability). It never trusts what the path says it did: the expected side is the generated data. It does not assert executor idleness afterwait_completion()(#210), only stored data.Tests (
tests/test_ingest_integrity.py, both wheels):insert_many(list, generator,parallel=True),insert_columns(sequential, parallel),insert_arrowandinsert_dataframe(sequential, parallel),insert_arrowinto a vertex type,create_vertices, asynccreate_record(parallel level 1 and 4) andcommand,append_samples. The sizes are 0, 1, 2 and one either side of every multiple of the chunk (7 rows, patched into the module constants) and ofcommit_everyandbatch_size(5 rows), and 255, 256 and 257 (the first reply of the native read path). One more load at the real 100,000create_verticeschunk.to_columns()andto_arrow()atbatch_size1, 2, 7, 255, 256, 257, 600 and 25,000 (the shape of the Native: column frames for to_arrow, to_columns, to_dataframe and to_polars, read by the decoder the JVM wheel uses (refs #312) #331 loss).new_edges: edge count (SQL and Cypher) and the endpoint pairs and weights, at every boundary, plain and weighted;close()straight after the last edges.run_in_transaction) and on different types with different paths, with a reader thread whose count may only grow and must end at the total.insert_many,insert_columns,insert_arrow,insert_dataframeandcreate_vertices, with the documented outcome exact (the committed batches stored, the batch with the bad row rolled back, the error raised, the message ofinsert_arrowandinsert_dataframenaming the committed row count); a column the declared type refuses stores nothing; a parallel duplicate is reported, nothing is stored twice and the stored keys survive a reopen.close()straight after the submissions stores everything or raises.Mutation proof (
test_mutation_*, 95 cases plus the seams). Every family runs through the same function with a fault and must report it: drop the last row, drop the first, skip a middle chunk, store a row twice, change one value, swap two values, and for the synchronous families load inside a transaction nobody commits (visible in the session, gone after the reopen: the message must name the reopen and not the call).test_mutation_inside_insert_manyputs the fault inside the path (the chunk function of each wheel),test_mutation_an_async_load_that_returns_before_the_waitparks the executor and checks before the wait,test_mutation_edgesdrops, duplicates and misroutes an edge, and two small files put a rows-dropped fault into the native columnar fast path (test_native_ingest_integrity_faults.py) and the JVM column conversion and bulk vertex path (test_jvm_ingest_integrity_faults.py, listed inNATIVE_NOT_APPLICABLE). The pure part of the check (digest, key check, every mutant) was run locally against a stub before the push.CI. This branch is
release/26.11.1(which is the26.11.1tag,2f28a328be) plus test files only, so a run of it is the run on the released behaviour; no throwaway base branch is needed. No CI result exists yet: the two fork runs I dispatched were cancelled with the rest of the fork queue. The tests will run first inside a combined candidate branch with the open PRs merged. Any test that fails on the released behaviour is a finding to file as its own issue (then a strictxfailnaming it), not a test to loosen.🤖 Generated with Claude Code