moonstate

One row, one case, four backends

The saver contract has five methods. Each row below is one case of the reference checkpoint-conformance inventory, read from one pinned commit (e5e37b5d70db) rather than from a moving branch. Each names the assertion in integration/src/conformance.mbt that exercises it, and each of those assertions runs on memory, sqlite, postgresql, mysql with the same expected value.

92 reference cases, plus one the suite does not name, make 93 rows in total. A row whose note says a concept is absent names the equivalent observable behaviour: this contract has no channel versions, metadata filters, namespaces beyond the thread id, or prune strategies. It stores whole states, filters pages by before and limit, and deletes a thread as one unit. Those differences are listed in the Conformance section of the README.

GET_TUPLE 11 cases

CaseWhat it checksCovered byBackends
test_get_tuple_nonexistent_returns_noneMissing thread returns None.conformance.mbt / test_get_tuple_nonexistent_returns_nonememory, sqlite, postgresql, mysql
test_get_tuple_latest_when_no_checkpoint_idReturns newest checkpoint when no checkpoint_id in config.conformance.mbt / test_get_tuple_latest_when_no_checkpoint_idmemory, sqlite, postgresql, mysql
test_get_tuple_specific_checkpoint_idReturns exact match when checkpoint_id specified.conformance.mbt / test_get_tuple_specific_checkpoint_idmemory, sqlite, postgresql, mysql
test_get_tuple_config_structureA tuple's config has no counterpart; the checkpoint's own thread, id and seq are checked.tuple.config has thread_id, checkpoint_ns, checkpoint_id.conformance.mbt / test_get_tuple_config_structurememory, sqlite, postgresql, mysql
test_get_tuple_checkpoint_fieldsAll Checkpoint fields present.conformance.mbt / test_get_tuple_checkpoint_fieldsmemory, sqlite, postgresql, mysql
test_get_tuple_metadataMetadata is not stored; step, the field a reader needs, is checked.metadata populated correctly.conformance.mbt / test_get_tuple_metadatamemory, sqlite, postgresql, mysql
test_get_tuple_parent_configparent_config when parent exists, None otherwise.conformance.mbt / test_get_tuple_parent_configmemory, sqlite, postgresql, mysql
test_get_tuple_pending_writespending_writes from put_writes visible.conformance.mbt / test_get_tuple_pending_writesmemory, sqlite, postgresql, mysql
test_get_tuple_pending_writes_in_writes_sort_key_orderThe SQL backends return writes sorted by task, so the assertion compares the sorted order.pending_writes come back in writes_sort_key order, not put or task_id order.conformance.mbt / test_get_tuple_pending_writes_in_writes_sort_key_ordermemory, sqlite, postgresql, mysql
test_get_tuple_respects_namespaceThere is one namespace in this contract: the thread id. Isolation between threads is checked.checkpoint_ns filtering.conformance.mbt / test_get_tuple_respects_namespacememory, sqlite, postgresql, mysql
test_get_tuple_nonexistent_checkpoint_idSpecific but missing checkpoint_id returns None.conformance.mbt / test_get_tuple_nonexistent_checkpoint_idmemory, sqlite, postgresql, mysql

PUT 18 cases

CaseWhat it checksCovered byBackends
test_put_returns_configput returns Unit; the checkpoint it wrote is read back instead.aput returns a RunnableConfig with thread_id, checkpoint_ns, checkpoint_id.conformance.mbt / test_put_returns_configmemory, sqlite, postgresql, mysql
test_put_roundtripput then get_tuple returns identical checkpoint.conformance.mbt / test_put_roundtripmemory, sqlite, postgresql, mysql
test_put_preserves_channel_valuesThe state is one JSON value, not a set of channels; several JSON shapes are round-tripped.Various types (str, int, list, dict, bytes, None) round-trip correctly.conformance.mbt / test_put_preserves_channel_valuesmemory, sqlite, postgresql, mysql
test_put_preserves_channel_versionsChannel versions are not stored; seq is the ordering of a thread's checkpoints.ChannelVersions round-trip correctly.conformance.mbt / test_put_preserves_channel_versionsmemory, sqlite, postgresql, mysql
test_put_preserves_versions_seenversions_seen is not stored; parent is the lineage a reader walks.versions_seen dict round-trips.conformance.mbt / test_put_preserves_versions_seenmemory, sqlite, postgresql, mysql
test_put_preserves_metadataMetadata is not stored; step is checked.Metadata source, step, parents, and custom keys round-trip.conformance.mbt / test_put_preserves_metadatamemory, sqlite, postgresql, mysql
test_put_root_namespaceA plain thread id is the root namespace here.checkpoint_ns='' works.conformance.mbt / test_put_root_namespacememory, sqlite, postgresql, mysql
test_put_child_namespaceA thread id containing a colon stands in for a child namespace.checkpoint_ns='child:abc' works.conformance.mbt / test_put_child_namespacememory, sqlite, postgresql, mysql
test_put_default_namespaceEvery checkpoint belongs to exactly one thread; no namespace argument is needed.Config without checkpoint_ns defaults to ''.conformance.mbt / test_put_default_namespacememory, sqlite, postgresql, mysql
test_put_multiple_checkpoints_same_threadSequential puts on same thread, all retrievable.conformance.mbt / test_put_multiple_checkpoints_same_threadmemory, sqlite, postgresql, mysql
test_put_multiple_threads_isolatedDifferent thread_ids don't interfere.conformance.mbt / test_put_multiple_threads_isolatedmemory, sqlite, postgresql, mysql
test_put_parent_configparent names the checkpoint this one was written on top of.parent checkpoint_id tracked correctly.conformance.mbt / test_put_parent_configmemory, sqlite, postgresql, mysql
test_put_incremental_channel_updateA checkpoint stores the whole state, so an earlier checkpoint's state is unchanged by a later put.Only updated channels need new blobs; unchanged channels loaded from prior versions.conformance.mbt / test_put_incremental_channel_updatememory, sqlite, postgresql, mysql
test_put_new_channel_addedA field appearing for the first time in a later state is read back from that state.A channel that appears for the first time in a later checkpoint.conformance.mbt / test_put_new_channel_addedmemory, sqlite, postgresql, mysql
test_put_channel_removedA field absent from a later state is absent when that state is read back.Channel no longer in channel_versions should not appear in loaded values.conformance.mbt / test_put_channel_removedmemory, sqlite, postgresql, mysql
test_put_preserves_run_idA run id is not stored; the thread id identifies the run.run_id in metadata round-trips correctly.conformance.mbt / test_put_preserves_run_idmemory, sqlite, postgresql, mysql
test_put_preserves_versions_seen_valuesseq and its value, rather than a versions_seen map, are checked.versions_seen values (not just keys) round-trip correctly.conformance.mbt / test_put_preserves_versions_seen_valuesmemory, sqlite, postgresql, mysql
put_replaces_an_existing_idNot a case of the reference suite; the contract's put documents it.Writing the same checkpoint id twice replaces the stored row.conformance.mbt / put_replaces_an_existing_idmemory, sqlite, postgresql, mysql

PUT_WRITES 10 cases

CaseWhat it checksCovered byBackends
test_put_writes_basicWrite stored, visible in aget_tuple pending_writes.conformance.mbt / test_put_writes_basicmemory, sqlite, postgresql, mysql
test_put_writes_multiple_writes_same_taskOne task files an array of steps, which is the same shape as several channel/value pairs.Multiple (channel, value) pairs in a single call.conformance.mbt / test_put_writes_multiple_writes_same_taskmemory, sqlite, postgresql, mysql
test_put_writes_multiple_tasksDifferent task_ids produce separate writes.conformance.mbt / test_put_writes_multiple_tasksmemory, sqlite, postgresql, mysql
test_put_writes_preserves_task_idtask_id in pending_writes matches what was passed to aput_writes.conformance.mbt / test_put_writes_preserves_task_idmemory, sqlite, postgresql, mysql
test_put_writes_preserves_channel_and_valueThe steps a task filed are round-tripped as JSON values.Channel name + value round-trip.conformance.mbt / test_put_writes_preserves_channel_and_valuememory, sqlite, postgresql, mysql
test_put_writes_task_pathThere is no separate task_path; the task string carries the path.task_path parameter accepted without error.conformance.mbt / test_put_writes_task_pathmemory, sqlite, postgresql, mysql
test_put_writes_idempotentFiling the same task again replaces its row rather than adding a second.Duplicate (task_id, idx) doesn't duplicate writes.conformance.mbt / test_put_writes_idempotentmemory, sqlite, postgresql, mysql
test_put_writes_special_channelsERROR and INTERRUPT are not special channels here; their JSON payloads are stored verbatim.ERROR and INTERRUPT channels handled correctly.conformance.mbt / test_put_writes_special_channelsmemory, sqlite, postgresql, mysql
test_put_writes_across_namespacesWrites are scoped by thread, the namespace this contract has.Writes isolated by checkpoint_ns.conformance.mbt / test_put_writes_across_namespacesmemory, sqlite, postgresql, mysql
test_put_writes_cleared_on_next_checkpointA new checkpoint has no writes filed against it.New checkpoint starts with fresh pending_writes.conformance.mbt / test_put_writes_cleared_on_next_checkpointmemory, sqlite, postgresql, mysql

LIST 16 cases

CaseWhat it checksCovered byBackends
test_list_allNo filters returns all checkpoints for the thread.conformance.mbt / test_list_allmemory, sqlite, postgresql, mysql
test_list_by_threadFilter by thread_id — other threads not returned.conformance.mbt / test_list_by_threadmemory, sqlite, postgresql, mysql
test_list_by_namespaceAnother thread's page is the namespace filter here.Filter by checkpoint_ns.conformance.mbt / test_list_by_namespacememory, sqlite, postgresql, mysql
test_list_orderinglist returns a thread's checkpoints oldest first; the page is read in that order.Newest first (descending checkpoint_id).conformance.mbt / test_list_orderingmemory, sqlite, postgresql, mysql
test_list_metadata_filter_single_keyThere is no metadata filter; before is the filter that narrows a page by checkpoint id.filter={'source': 'input'} returns only input checkpoints.conformance.mbt / test_list_metadata_filter_single_keymemory, sqlite, postgresql, mysql
test_list_metadata_filter_stepThere is no metadata filter; limit is the filter that narrows a page by size.filter={'step': 1} returns matching checkpoints.conformance.mbt / test_list_metadata_filter_stepmemory, sqlite, postgresql, mysql
test_list_beforePagination cursor — only checkpoints before the given one.conformance.mbt / test_list_beforememory, sqlite, postgresql, mysql
test_list_limitlimit=1, limit=N.conformance.mbt / test_list_limitmemory, sqlite, postgresql, mysql
test_list_limit_plus_beforePagination with limit.conformance.mbt / test_list_limit_plus_beforememory, sqlite, postgresql, mysql
test_list_combined_thread_and_filterthread, before and limit are combined in one call.thread_id + metadata filter combined.conformance.mbt / test_list_combined_thread_and_filtermemory, sqlite, postgresql, mysql
test_list_empty_resultNo matches returns empty.conformance.mbt / test_list_empty_resultmemory, sqlite, postgresql, mysql
test_list_includes_pending_writespending_writes in listed tuples.conformance.mbt / test_list_includes_pending_writesmemory, sqlite, postgresql, mysql
test_list_multiple_namespacesTwo threads' pages are read separately.Root namespace checkpoint listed correctly.conformance.mbt / test_list_multiple_namespacesmemory, sqlite, postgresql, mysql
test_list_metadata_filter_multiple_keysbefore and limit together are the two bounds of a page.filter with multiple keys — all must match.conformance.mbt / test_list_metadata_filter_multiple_keysmemory, sqlite, postgresql, mysql
test_list_metadata_filter_no_matchA before cursor older than every checkpoint yields an empty page.Multi-key filter that matches nothing returns empty.conformance.mbt / test_list_metadata_filter_no_matchmemory, sqlite, postgresql, mysql
test_list_metadata_custom_keysA caller filters the returned page; the saver's two bounds stay composable.Custom (non-standard) metadata keys are filterable.conformance.mbt / test_list_metadata_custom_keysmemory, sqlite, postgresql, mysql

DELETE_THREAD 5 cases

CaseWhat it checksCovered byBackends
test_delete_thread_removes_checkpointsAll checkpoints gone after delete.conformance.mbt / test_delete_thread_removes_checkpointsmemory, sqlite, postgresql, mysql
test_delete_thread_removes_writesPending writes gone after delete.conformance.mbt / test_delete_thread_removes_writesmemory, sqlite, postgresql, mysql
test_delete_thread_removes_all_namespacesDeleting both threads removes both namespaces.Root + child namespaces both removed.conformance.mbt / test_delete_thread_removes_all_namespacesmemory, sqlite, postgresql, mysql
test_delete_thread_preserves_other_threadsOther threads untouched.conformance.mbt / test_delete_thread_preserves_other_threadsmemory, sqlite, postgresql, mysql
test_delete_thread_nonexistent_noopNo error for missing thread.conformance.mbt / test_delete_thread_nonexistent_noopmemory, sqlite, postgresql, mysql

COPY_THREAD 8 cases

CaseWhat it checksCovered byBackends
test_copy_thread_basicA copy is list + put + put_writes over the public contract, not a saver method.Checkpoints appear on target thread.conformance.mbt / test_copy_thread_basicmemory, sqlite, postgresql, mysql
test_copy_thread_all_checkpointsThe copy takes the whole page, not only the latest checkpoint.All checkpoints copied, not just latest.conformance.mbt / test_copy_thread_all_checkpointsmemory, sqlite, postgresql, mysql
test_copy_thread_preserves_metadataseq and step survive the copy.Metadata intact on copied checkpoints.conformance.mbt / test_copy_thread_preserves_metadatamemory, sqlite, postgresql, mysql
test_copy_thread_preserves_namespacesBoth source threads are copied to their own target threads.Root + child namespaces copied.conformance.mbt / test_copy_thread_preserves_namespacesmemory, sqlite, postgresql, mysql
test_copy_thread_preserves_writesPending writes copied.conformance.mbt / test_copy_thread_preserves_writesmemory, sqlite, postgresql, mysql
test_copy_thread_preserves_orderingThe target's page has the source's order.Checkpoint order maintained.conformance.mbt / test_copy_thread_preserves_orderingmemory, sqlite, postgresql, mysql
test_copy_thread_source_unchangedSource thread still intact after copy.conformance.mbt / test_copy_thread_source_unchangedmemory, sqlite, postgresql, mysql
test_copy_thread_nonexistent_sourceAn empty source page produces an empty target.Graceful handling of non-existent source thread.conformance.mbt / test_copy_thread_nonexistent_sourcememory, sqlite, postgresql, mysql

DELETE_FOR_RUNS 7 cases

CaseWhat it checksCovered byBackends
test_delete_for_runs_singleA run is one thread; deleting one thread is deleting one run.One run_id removed.conformance.mbt / test_delete_for_runs_singlememory, sqlite, postgresql, mysql
test_delete_for_runs_multipleDeleting several threads is one call per thread.List of run_ids removed.conformance.mbt / test_delete_for_runs_multiplememory, sqlite, postgresql, mysql
test_delete_for_runs_preserves_other_runsUnrelated runs untouched.conformance.mbt / test_delete_for_runs_preserves_other_runsmemory, sqlite, postgresql, mysql
test_delete_for_runs_removes_writesAssociated writes cleaned up.conformance.mbt / test_delete_for_runs_removes_writesmemory, sqlite, postgresql, mysql
test_delete_for_runs_empty_list_noopEmpty list no error.conformance.mbt / test_delete_for_runs_empty_list_noopmemory, sqlite, postgresql, mysql
test_delete_for_runs_nonexistent_noopMissing run_ids no error.conformance.mbt / test_delete_for_runs_nonexistent_noopmemory, sqlite, postgresql, mysql
test_delete_for_runs_across_namespacesThreads with different id shapes are all removed.All namespaces cleaned.conformance.mbt / test_delete_for_runs_across_namespacesmemory, sqlite, postgresql, mysql

DELTA_CHANNEL_HISTORY 10 cases

CaseWhat it checksCovered byBackends
test_history_returns_writes_oldest_firsthistory and list both return a thread oldest first.Writes are returned oldest-to-newest.conformance.mbt / test_history_returns_writes_oldest_firstmemory, sqlite, postgresql, mysql
test_history_seed_is_nearest_snapshotparent names the nearest ancestor checkpoint.Seed is the value from the nearest ancestor with channel_values populated.conformance.mbt / test_history_seed_is_nearest_snapshotmemory, sqlite, postgresql, mysql
test_history_excludes_target_pending_writesWrites are filed against one checkpoint, never inherited by the next.Target's own pending_writes are NOT included in the history.conformance.mbt / test_history_excludes_target_pending_writesmemory, sqlite, postgresql, mysql
test_history_multi_channelSeveral fields of one JSON state are read back together.Multiple channels have independent walk termination.conformance.mbt / test_history_multi_channelmemory, sqlite, postgresql, mysql
test_history_empty_channels_returns_emptyA before cursor older than every checkpoint yields an empty page.Empty channels list returns empty mapping.conformance.mbt / test_history_empty_channels_returns_emptymemory, sqlite, postgresql, mysql
test_history_walk_to_root_no_seedThe first checkpoint has no parent.Walk reaches root without finding seed — no 'seed' key in result.conformance.mbt / test_history_walk_to_root_no_seedmemory, sqlite, postgresql, mysql
test_history_migration_plain_value_as_seedA scalar JSON state round-trips like an object state.Pre-delta plain value in channel_values acts as seed (migration case).conformance.mbt / test_history_migration_plain_value_as_seedmemory, sqlite, postgresql, mysql
test_history_seed_ancestor_own_writes_are_replayedWrites filed against an ancestor are still there when that ancestor is read.Writes stored AT the seed ancestor must be included in `writes`.conformance.mbt / test_history_seed_ancestor_own_writes_are_replayedmemory, sqlite, postgresql, mysql
test_history_orders_parallel_writes_by_task_pathWrites are compared in task order.Writes from parallel tasks replay in task_path order, not task_id order.conformance.mbt / test_history_orders_parallel_writes_by_task_pathmemory, sqlite, postgresql, mysql
test_history_orders_pathless_writes_firstA task named as graph input sorts before named node tasks.Writes stored without a task_path (graph input) replay before task writes.conformance.mbt / test_history_orders_pathless_writes_firstmemory, sqlite, postgresql, mysql

PRUNE 8 cases

CaseWhat it checksCovered byBackends
test_prune_keep_latest_single_threadThere is no prune method; list(limit=1) is the latest checkpoint a reader keeps.Only latest checkpoint survives.conformance.mbt / test_prune_keep_latest_single_threadmemory, sqlite, postgresql, mysql
test_prune_keep_latest_multiple_threadsEach thread keeps its own latest page.Each thread keeps its latest.conformance.mbt / test_prune_keep_latest_multiple_threadsmemory, sqlite, postgresql, mysql
test_prune_keep_latest_across_namespacesThreads with different id shapes each keep one checkpoint.Latest per namespace kept.conformance.mbt / test_prune_keep_latest_across_namespacesmemory, sqlite, postgresql, mysql
test_prune_keep_latest_preserves_writesThe latest checkpoint still carries its writes.Latest checkpoint's writes kept.conformance.mbt / test_prune_keep_latest_preserves_writesmemory, sqlite, postgresql, mysql
test_prune_delete_alldelete removes every checkpoint of a thread.delete_all strategy removes everything.conformance.mbt / test_prune_delete_allmemory, sqlite, postgresql, mysql
test_prune_preserves_other_threadsDeleting one thread leaves the others.Unlisted threads untouched.conformance.mbt / test_prune_preserves_other_threadsmemory, sqlite, postgresql, mysql
test_prune_empty_list_noopDeleting an empty list of threads changes nothing.Empty thread_ids no error.conformance.mbt / test_prune_empty_list_noopmemory, sqlite, postgresql, mysql
test_prune_nonexistent_noopDeleting a thread that is not there is not an error.Missing threads no error.conformance.mbt / test_prune_nonexistent_noopmemory, sqlite, postgresql, mysql

The registry is pinned too

Span names are checked against a semantic-convention registry at one pinned commit, e6658f14c9d9ea0760825f029cb82e7673f48fab, recorded in scripts/weaver_registry_pin.txt. A check that follows a default branch can turn red on a change nobody in this repository made.