Skip to content

fix(catalog): version the .cache wire format so parser changes auto-invalidate#19

Merged
ale-rinaldi merged 1 commit into
mainfrom
fix/issue-5-cache-versioning
May 15, 2026
Merged

fix(catalog): version the .cache wire format so parser changes auto-invalidate#19
ale-rinaldi merged 1 commit into
mainfrom
fix/issue-5-cache-versioning

Conversation

@ale-rinaldi

Copy link
Copy Markdown
Contributor

Closes #5.

What changed

pkg/catalog/cache.go wraps the on-disk gob payload with a tiny header:

type cacheFile struct {
    Magic         string  // "mythy-catalog-cache"
    SchemaVersion int     // parserSchemaVersion
    Template      *Template
}

SaveCache always emits the wrapper. LoadCache verifies the magic and version before unwrapping; any mismatch routes to ErrCacheStale. The pre-existing source-XML-mtime check is kept — it still catches the "I edited the catalog by hand" case independently of the schema version.

Bumping policy

parserSchemaVersion is a constant at the top of cache.go, currently 1. The doc comment spells out the rule: any PR that changes how pkg/catalog/ encodes a Template (struct field added, dropped, semantics-rewritten, or any load-time pass mutates the result) bumps the version. Reviewers should treat unbumped pkg/catalog/ diffs as suspicious.

Backwards compatibility

Pre-versioning caches encoded a bare *Template directly. After this PR LoadCache tries to decode them into the new cacheFile wrapper and gets a gob error or a malformed wrapper; either way it returns ErrCacheStale and the caller regenerates. Verified by TestLoadCacheRejectsLegacyUnwrappedFormat.

Tests

  • TestLoadCacheRejectsLegacyUnwrappedFormat — writes a bare *Template (the pre-fix format), asserts LoadCache returns ErrCacheStale.
  • TestLoadCacheRejectsWrongSchemaVersion — writes a wrapper with parserSchemaVersion + 1, asserts the same.
  • Existing TestCacheRoundTrip / TestCacheStaleOnMtime / TestLoadCacheResolvesTypedefsForStaleCaches pass unchanged through the new wrapper.

Live verification

Pre-PR cache on disk: ~/gridsociety/thytronic-templates/us/NV10P-EB0-u.cache (1931115 bytes, mtime 13:13, written by an older mythy build). After running any mythy command with this PR's binary, the cache regenerates: same path, mtime advanced, size grew by 91 bytes (the wrapper header), and subsequent invocations load the new-format cache without re-parsing. The migration is silent.

🤖 Generated with Claude Code

…nvalidate

The catalog cache used to be stale-checked by source-XML mtime only.
When a parser change reshapes the in-memory Template / Data / Class
without touching the XML, on-disk caches stayed "fresh" and got loaded
verbatim — silently feeding the new mythy binary the old parser's
output. Anyone upgrading mythy needed to manually wipe Templates/*.cache
to see the fix take effect, including during normal development.

Wrap every cache file with a small versioned header (magic string +
schema version int) ahead of the gob-encoded Template, both written
by SaveCache and verified by LoadCache. Any mismatch — wrong magic,
wrong version, or any decode failure — routes to ErrCacheStale and
the caller falls back to ParseTemplate, which writes a fresh cache.

parserSchemaVersion starts at 1 and gets bumped from now on whenever
a PR changes how pkg/catalog/ encodes a Template. Pre-versioning
caches (bare *Template gob) decode into the new wrapper as malformed
data and are correctly rejected — confirmed by test.

Closes #5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ale-rinaldi ale-rinaldi merged commit 27bb37e into main May 15, 2026
2 checks passed
@ale-rinaldi ale-rinaldi deleted the fix/issue-5-cache-versioning branch May 15, 2026 11:20
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.

Template .cache files are not invalidated when the catalog parser changes

1 participant