Skip to content

fix: prevent partial preformatted cache after interrupted update#884

Open
benthamite wants to merge 1 commit into
emacs-citar:mainfrom
benthamite:fix/preformat-cache-atomicity
Open

fix: prevent partial preformatted cache after interrupted update#884
benthamite wants to merge 1 commit into
emacs-citar:mainfrom
benthamite:fix/preformat-cache-atomicity

Conversation

@benthamite
Copy link
Copy Markdown
Contributor

Summary

citar-cache--preformat-bibliography previously updated the bib's preformatted hash in place via clrhash followed by maphash + puthash. If the refill is interrupted partway through — for example, C-g during an idle-time update of a large bibliography — the preformatted hash is left with only a fraction of the entries. Because citar-cache--update-bibliography has already set props before calling the preformatter, subsequent cache-up-to-date checks see "no changes needed" and the partial preformatted cache persists indefinitely. citar--format-candidates then errors with

No preformatted candidate string: <KEY>

on any entry that didn't make it into the hash before the interruption, breaking citar-insert-citation, citar-select-refs, etc.

I hit this against a ~15k-entry bibliography: after some earlier interruption, the bib's entries cache had 14,662 keys but the preformatted cache only had 7,986. The partial state then persisted across Emacs sessions until citar-cache--preformat-bibliography was called manually.

Fix

Build the new preformatted hash in a fresh local hash table and replace the bib slot via setf only after maphash completes. If the maphash is interrupted, the setf never runs and the existing (valid) preformatted hash is retained.

This mirrors the atomicity pattern introduced in #882 for the entries slot.

Test plan

  • Exercised the patched function against the affected bibliography; preformatted is fully populated (14,662/14,662) and the previously missing key resolves.
  • Verified the hash is a fresh object (eq returns nil against the old slot value), confirming the atomic swap.
  • Byte-compiles cleanly.

citar-cache--preformat-bibliography previously called (clrhash
preformatted) on the bib's cached hash and then refilled it in place
via maphash + puthash. If the refill was interrupted partway through
— e.g., C-g during an idle-time update of a large bibliography —
the preformatted hash was left with only a fraction of the entries.
Because citar-cache--update-bibliography had already set `props'
before calling this function, subsequent cache checks saw "no
changes needed" and the partial preformatted cache persisted
indefinitely, causing citar--format-candidates to error with "No
preformatted candidate string: KEY" on any entry that didn't make
it into the hash before the interruption.

Fix by building the new preformatted hash in a fresh local hash
table and replacing the bib slot via setf only after maphash
completes. If the maphash is interrupted, the setf never runs and
the existing (valid) preformatted hash is retained.

This mirrors the atomicity pattern introduced in emacs-citar#882 for the
entries slot.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant