synology_apm_repo.sdk.storage.generations module¶
S3/Azure db/<name>.<N> generation selection (FORMAT-SPEC.md:
generation-selection). The single place this rule lives; dircache.py, seqid.py,
s3.py and dedup/repository.py’s db() all point here rather than
restating it.
Why the naive “largest ``.<N>`` suffix” rule (resolve_seq_file)
is not enough here, unlike every other per-generation file this SDK
reads: a db/<name> generation can be written to S3/Azure before the
transaction that references it is actually committed, so the largest
suffix present can be a not-yet-committed or long-superseded generation.
The correct answer needs the transaction log:
``latest_txn`` (
latest_transaction_id): the largestrepo_transactions/repo_transaction.<N>filename, opened and parsed — the answer is that file’s embeddedtransaction_id, never the filename’s own<N>(the two are not the same number).``file_map``/``repo_info`` (anything not in
SUPPLEMENTAL_TABLES): amongdb/<name>.<N>’s suffixes, the largest one strictly less thanlatest_txn— a generation written at or after the latest committed transaction is exactly the “written but not yet committed” case above.The 9 supplemental tables (
SUPPLEMENTAL_TABLES) use an independent, simpler rule: the largest suffix that also has a matchingsuppl_transaction_ids/<N>marker file — a numbering completely unrelated torepo_transactions/’s own.
A logical name with no .<N> variant at all falls back to the
bare, unsuffixed name — the same file the naive rule would have picked
anyway.
- synology_apm_repo.sdk.storage.generations.SUPPLEMENTAL_TABLES = frozenset({'agent_connection', 'connection_config', 'copy_file', 'copy_source_version', 'copy_target_file', 'copy_target_version', 'copy_target_version_meta', 'file_meta', 'workload_config'})¶
This project’s supplemental-table set — resolved by the
suppl_transaction_ids/marker rule, not the transaction-log rule. See FORMAT-SPEC.md: generation-selection.copy_target_fileshares its physical file withcopy_target_version(same on-disk name) but is listed here anyway for completeness — seePHYSICAL_NAME_ALIASESfor where that sharing is actually enforced, not just documented.
- synology_apm_repo.sdk.storage.generations.PHYSICAL_NAME_ALIASES: dict[str, str] = {'copy_target_file': 'copy_target_version'}¶
Logical
db/<name>names that are not their own on-disk object at all —copy_target_filehas nocopy_target_file[.N]object anywhere on a real repository; thecopy_target_filetable lives inside whichever generationcopy_target_version[.N]resolves to (same physical sqlite file — both tables are written through one connection on the write side). Without this alias,DedupRepo.db("copy_target_file")would searchdb/for an object literally named that and raiseNotFoundError— there is none — starving the PC/PS browse path (PcpsDiskTree.object_nodes()) of its whole object list. Consulted byDedupRepo.dbbefore any generation resolution happens, so it applies uniformly on bothVAULTandOBJECT_STORElayouts — this is a fact about how the two tables are physically stored, not an object-store-specific generation-selection quirk.
- async synology_apm_repo.sdk.storage.generations.latest_transaction_id(store, transactions_dir)¶
The latest committed transaction id, per FORMAT-SPEC.md: generation-selection.
- async synology_apm_repo.sdk.storage.generations.resolve_generation(store, db_dir, name, *, transactions_dir, suppl_dir)¶
The correct
db/<name>[.<N>]logical path fornameon anOBJECT_STORElayout: the largest.<N>strictly less than the latest committed transaction for most tables, or the largest.<N>with a matchingsuppl_transaction_idsmarker for the 9 supplemental tables (FORMAT-SPEC.md: generation-selection).db_dir/transactions_dir/suppl_dirare already joined withlayout.repo_rootby the caller.Raises
NotFoundErrorifnamehas.<N>variants present but none of them is actually valid per the rule that applies to it (a genuinely inconsistent/partial repository copy, not something this function should silently paper over).