Route account writes for the split Fava ledger layout #32
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/split-ledger"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Companion to
aiolabs/server-deploy#4(Fava module: split/var/lib/fava/ledger.beancountinto purpose-specific include files). Adapts libra's two ledger-write paths to the new layout.Closes #28, closes #29.
Summary
fava_client.add_account: newtarget_fileparameter +_infer_target_filehelper that routes user-account opens (:User-[0-9a-f]{8}$) toaccounts/users.beancountand everything else toaccounts/chart.beancount. Falls back to inference when callers don't pass it explicitly.fava_client._resolve_target_file: hot-fix discovered during live testing — fava's/api/sourcerejects relative paths with HTTP 500 (NonSourceFileError). Resolver prepends the absolute dirname of the root ledger (cached on the singleton after firstGET /api/options, guarded by anasyncio.Lockso concurrent first-callers don't double-fetch).'open 'or current-year-dated lines, so 1970-* seed opens were invisible). Post-split each include has one mutation profile and append-only is cleaner; new entries land at end of file.POST /api/v1/admin/accounts(new endpoint): super-user-only; takes{name, currencies, description?}; writes the Open toaccounts/chart.beancountand syncs into libra's DB viasync_single_account_from_beancount. Validates the name against the five Beancount top-level prefixes. Backs the upcoming admin chart-edit UI (libra#30).account_sync.sync_single_account_from_beancount: now reads the full user_id from Beancount metadata when present, falling back to the name-derived 8-char prefix. crud.py writes the full user_id into metadata when callingfava.add_account, so the post-sync row matches whatget_or_create_user_accountqueries for — kills three lines of warning churn per user-account creation that went through the UNIQUE-constraint recovery path.tasks.wait_for_account_syncawaits a newfava_client.wait_for_fava_client()helper backed by anasyncio.Event. Previously the sync task started inlibra_start()raced the fire-and-forget_init_fava()coroutine and reliably crashed the first iteration withFava client not initialized.Verified on aio-demo (live)
After
./deploy.sh aio-demowith/var/lib/favawiped, then manual sync of the libra files:/var/lib/fava/accounts/users.beancount;accounts/chart.beancountuntouchedPOST /api/v1/admin/accounts(three SmokeTest entries) → landed inaccounts/chart.beancount; last one at the very bottom (always-append verified)!-flagged drill purchase) → landed intransactions.beancountvia fava'sdefault-filerouting!→*on the same line; no collateral edits to any other file. Log line confirmed fava reportsmeta['filename']as the absolute path to the include file, which/api/sourceaccepts as-is.bean-checkPASS across all three entriessudo -u fava bash -c 'echo x >> options.beancount'→Permission denied; same ontransactions.beancountsucceeds. Server-deploy@29e9b09 chmod'd ledger/options/commodities to 0440.⚠️ Catalog-bump rollout — cfaun upgrade must wait
Once this is merged and the catalog version is bumped, ANY host pointing at our manifest can pull the new libra via the lnbits admin UI's "Upgrade" button. Do not click Upgrade on cfaun until
aiolabs/server-deploy#6(cfaun ledger migration) has run. Running this libra against cfaun's still-monolithic/var/lib/fava/ledger.beancountwould misroute every write (Opens to non-existentaccounts/{chart,users}.beancount, transactions to a non-existent default-file route).aio-demo is already on the split layout (deployed earlier in this session) so its Upgrade is safe whenever.
The original "find last Open directive, insert after its metadata" logic was a clever optimisation for the monolithic ledger where opens, txns, and assertions all lived in one file -- you wanted new opens grouped with existing opens, not appended after a long transaction tail. Post-split, each include file has one mutation profile: - accounts/chart.beancount: only Open directives - accounts/users.beancount: only Open directives - transactions.beancount: only Transactions There is no longer a content shape that benefits from mid-file insertion; the existing heuristic also had a pre-existing bug where it only matched 'open ' OR '{current_year}-' as line prefixes, so 1970-* seed opens were invisible and the search "stuck" to the first current-year line in the file (which on aio-demo ended up being the wrong place). Drop the search; always append. Simpler, chronological, append-only friendly. Refs: aiolabs/libra#28