feat: write-through file cache for external readers - #18
Open
skomae wants to merge 1 commit into
Open
Conversation
Mirror every fetch into a plain-YAML cache under $XDG_CACHE_HOME/fjira/ (~/.cache/fjira/) so external tools can read issue state without hitting Jira. Off by default; enabled via manage.cache.files in fjira.yaml or FJIRA_CACHE_FILES=1, with a writer-side TTL (manage.cache.expires / FJIRA_CACHE_EXPIRES, default 3w) reaped on startup. - internal/cache: envelope + issue/search/children entry types, atomic temp+rename writes, replace-in-place (one file per entity, dated by local fetch day), JQL-hash filenames (first 16 hex of SHA-256 over the exact query bytes), TTL reaper, and a jira.Api decorator that caches GetIssueDetailed, SearchJql, and page 0 of SearchJqlPageable; the epic-children query lands under children/<KEY> - internal/os: MustGetFjiraCacheDir (XDG_CACHE_HOME, ~/.cache fallback) - internal/workspaces: manage.cache settings block (survives fjira.yaml rewrites) + env overrides - internal/jira: capture cloud accountType on User, mapped to the cache comments' authorType (human/bot) Cache writes are best-effort and never fail or serve a fetch; fjira stays live-only. No credentials are ever written. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds an opt-in, plain-YAML file cache that fjira writes as a side effect of normal use, so external tools can read issue state without hitting Jira. Covers the first three writer work items of the cache contract: cache-dir resolution, config keys, the cache store package, and API write-through.
How
internal/cache(new): envelope types (v/kind/workspace/fetchedAt), issue/search/children entry schemas, atomic temp-file+rename writes, replace-in-place (one file per entity, named<id>.<local-date>.yaml, older dates unlinked), JQL-hash filenames (first 16 hex of SHA-256 over the exact query bytes, pinned by test vector), TTL parser (3w/10d/36h), and an mtime-based reaper.cache.WrapApiwrapsjira.Apiat the single fetch choke point —GetIssueDetailed→issue/,SearchJql→search/, and the epic-children query (parent = "KEY" ORDER BY key ASC) →children/<KEY>.SearchJqlPageablecaches page 0 only so later pages can't clobber the snapshot with a mid-list slice. Per-keystroke fuzzySearch()is deliberately not cached. Cache writes are best-effort: they never fail a fetch, and fjira never reads the cache.manage.cache.files(defaultfalse) /manage.cache.expires(default3w) infjira.yaml, withFJIRA_CACHE_FILES/FJIRA_CACHE_EXPIRESenv overrides. Themanage:block lives on theSettingsstruct so whole-file rewrites (e.g. issue-filter persistence) preserve a hand-added block — tested.internal/os:MustGetFjiraCacheDir()—$XDG_CACHE_HOME/fjira, falling back to~/.cache/fjira; deterministic from env alone (no existence probing) so external readers resolve the identical path.internal/jira: capture Jira Cloud'saccountTypeonUser, mapped toauthorType: human|boton cached comments (empty when not derivable, e.g. Jira Server).Testing
TEST-1vsTEST-12), reaper, entry mapping, decorator routing, and the disabled-by-default no-op path.wrapApiWithCacheWriteagainst a mock HTTP Jira and asserts the file lands under<cache>/fjira/<workspace>/issue/.go test ./internal/...green;go vet+gofmtclean. (cmd/fjira-cli/commandstests fail without a tty — pre-existing on master, unrelated.)Notes
--jsonsubcommands,lookup/id table) are deliberately out of scope for this PR.🤖 Generated with Claude Code