Skip to content

refactor[next]: name the cache layout and give the translation caches one home - #2769

Merged
havogt merged 1 commit into
mainfrom
havogt/next-cache-dir-rename
Aug 20, 2026
Merged

refactor[next]: name the cache layout and give the translation caches one home#2769
havogt merged 1 commit into
mainfrom
havogt/next-cache-dir-rename

Conversation

@havogt

@havogt havogt commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

The layout of the generated-code cache was spelled out as string literals at the
places that happen to write it:

Literal Written in
"translation_cache" / "gtfn_cache" each backend's workflow factory
"_pyext" cache.get_cache_folder
"compile_commands_cache" the compiledb build system, as a function-local

Nothing named these, so reading a cache directory meant recognizing conventions
rather than looking them up, and anything outside the writer had to re-spell
them.

.gt4py_cache/
├── translation_cache/                    <- DaCe translation payloads only
├── gtfn_cache/                           <- gtfn translation payloads only
├── lap_program_pyext_<fp>_<version>/     <- build: liblap_program.so, program.sdfgz
└── compile_commands_cache_..._pyext_.../ <- shared compiledb

Each literal becomes a name in the module that owns it: BINDINGS_NAME_SUFFIX,
TRANSLATION_CACHE_DIR_NAME and TRANSLATION_CACHE_BACKENDS in
otf/compilation/cache.py, and COMPILEDB_PROTOTYPE_NAME_PREFIX in the
compiledb build system.

The inconsistent pair gets one home, stage first and backend second, reached
through get_translation_cache_folder(cache_base, backend) so callers no longer
assemble the path:

.gt4py_cache/
└── translation_cache/
    ├── dace/   <hash>.pkl
    └── gtfn/   <hash>.pkl

@havogt
havogt changed the base branch from havogt/next-cache-manager to main August 10, 2026 14:05
@havogt
havogt force-pushed the havogt/next-cache-dir-rename branch from 4df0e9c to 5813e34 Compare August 10, 2026 14:05
@havogt havogt changed the title refactor[next]: give the two translation caches one home refactor[next]: name the cache layout and give the translation caches one home Aug 10, 2026
@havogt
havogt force-pushed the havogt/next-cache-dir-rename branch from 5813e34 to 25611b6 Compare August 10, 2026 14:16
@havogt
havogt requested a review from edopao August 10, 2026 14:30
@havogt
havogt marked this pull request as ready for review August 10, 2026 14:31

@edopao edopao left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a minor comment.

@@ -47,8 +47,9 @@ class Params:
input_fingerprinter=stages.compilable_program_fingerprinter,
cache=filecache.FileCache(
str(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The FileCache constructor accepts path: str | os.PathLike, so it should be possible to avoid the str conversion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — dropped the str() in factory.py; FileCache resolves the Path itself. It also removes the extra nesting this diff had introduced.

input_fingerprinter=stages.compilable_program_fingerprinter,
cache=filecache.FileCache(
str(cache.get_cache_base_path(config.BUILD_CACHE_LIFETIME) / "gtfn_cache")
str(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — dropped the str() in gtfn.py; FileCache resolves the Path itself. It also removes the extra nesting this diff had introduced.

@havogt
havogt force-pushed the havogt/next-cache-dir-rename branch from 25611b6 to a752914 Compare August 10, 2026 14:46
@havogt
havogt requested a lite review from Copilot August 10, 2026 14:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Refactors cache directory naming by centralizing previously inlined literals, and consolidates translation caches into a single parent directory with per-backend subfolders.

Changes:

  • Introduces named constants for cache layout (bindings suffix, translation cache dir name, translation backends, compiledb prototype prefix).
  • Adds get_translation_cache_folder(cache_base, backend) and updates DaCe/gtfn runners to use it.
  • Updates tests to assert the new cache naming/layout behavior.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/next_tests/unit_tests/otf_tests/compilation_tests/test_cache.py Updates assertions to use named constants and adds coverage for shared translation cache parent dir.
src/gt4py/next/program_processors/runners/gtfn.py Switches gtfn translation cache path construction to get_translation_cache_folder(...).
src/gt4py/next/program_processors/runners/dace/workflow/factory.py Switches DaCe translation cache path construction to get_translation_cache_folder(...).
src/gt4py/next/otf/compilation/cache.py Adds constants and get_translation_cache_folder(...); updates bindings suffix usage in build cache folder naming.
src/gt4py/next/otf/compilation/build_systems/compiledb.py Names the compiledb synthetic cache folder prefix constant and uses it in name generation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +153 to 156
cache.get_translation_cache_folder(
cache.get_cache_base_path(config.BUILD_CACHE_LIFETIME), "gtfn"
)
),
Comment on lines +55 to +57
def get_translation_cache_folder(cache_base: pathlib.Path, backend: str) -> pathlib.Path:
"""Return the folder under `cache_base` where `backend` caches its translations."""
return cache_base / TRANSLATION_CACHE_DIR_NAME / backend
Comment on lines +55 to +57
def get_translation_cache_folder(cache_base: pathlib.Path, backend: str) -> pathlib.Path:
"""Return the folder under `cache_base` where `backend` caches its translations."""
return cache_base / TRANSLATION_CACHE_DIR_NAME / backend
Comment on lines +34 to +37
#: Suffix appended by `get_cache_folder` to the program name when the cached
#: artifact includes bindings. It is part of the pattern's `name` group, so
#: recovering the plain program name means stripping this suffix.
BINDINGS_NAME_SUFFIX: Final[str] = "_pyext"
slug = ext_source.program_source.entry_point.name
if ext_source.binding_source:
slug = f"{slug}_pyext"
slug = f"{slug}{BINDINGS_NAME_SUFFIX}"
… one home

The layout of the generated-code cache was spelled out as string literals at the
places that happen to write it: the translation cache directory in each backend's
workflow factory, the bindings suffix in `get_cache_folder`, the compile-complete
marker in the DaCe compile step, the compiledb prototype name in the compiledb
build system. Nothing named these, so reading a cache directory meant recognizing
conventions rather than looking them up, and anything outside the writer had to
re-spell them.

Name each in the module that owns it, and fix the one that was inconsistent while
doing so. The two caches holding translation-step output were called
`translation_cache/` for DaCe -- a name for the stage, but holding one backend's
entries -- and `gtfn_cache/` for gtfn, a name for the backend that says nothing
about the stage. Neither holds build artifacts; those sit in sibling
`<program>_pyext_<fingerprint>_<version>` folders. They now share one parent,
`translation_cache/<backend>/`, reached through `get_translation_cache_folder`,
so both read stage first and backend second, the pair is visible as a pair, and
clearing every translation cache is one directory rather than a list that grows
with each backend.

Entries under the previous names are not migrated. They are already discarded on
any change of the build-cache version, so leaving them to be recomputed matches
what this cache does routinely; the stale directories can simply be removed.
@havogt
havogt force-pushed the havogt/next-cache-dir-rename branch from a752914 to 16d6c20 Compare August 10, 2026 15:27
@havogt

havogt commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Thanks — going through the Copilot comments, one of them earned a change and the
rest do not hold. Noting the checks so they are not re-litigated (the review
banner says it ran degraded: "couldn't run its full agentic review because it
didn't start before the timeout"
).

FileCache may not accept os.PathLike — it does, and this was @edopao's
request on these exact lines:

def __init__(self, path: str | os.PathLike):
    self.path = pathlib.Path(path).resolve()

Verified FileCache(p).path == FileCache(str(p)).path.

get_translation_cache_folder should mkdir and resolve like
get_cache_folder
— the useful one, though the conclusion is inverted. Both
concerns are already covered downstream: FileCache.__init__ resolves, and
FileCache.__setitem__ does mkdir(parents=True, exist_ok=True) before writing.
Creating the folder here would be actively wrong: the cache manager in #2768
calls this for inspection, so gt4py-next-cache path --cache-dir <somewhere>
would create directories merely by reporting where they are. That contract was
implicit, so I have documented it:

    Unlike `get_cache_folder`, this only computes a path. The folder is created by
    the cache that writes into it, so that asking where a cache would be does not
    create itwhich tools that only inspect a cache rely on.

Path traversal if backend contains ../backend is not user-controlled:
two call sites pass string literals, and the CLI takes it from
argparse(choices=[*TRANSLATION_CACHE_BACKENDS, "all"]), which rejects anything
else (--backend '../../etc'invalid choice). Adding a guard for an
unreachable input is the kind of defensive check this codebase does not carry.

Derive the _pyext part of CACHE_FOLDER_NAME_PATTERN from
BINDINGS_NAME_SUFFIX
(raised twice) — the pattern contains no such literal:
(?P<name>.+)_(?P<fingerprint>…)_(?P<version_id>…) absorbs the suffix into
name, which is why consumers strip it with removesuffix. There is nothing to
derive, so there is nothing that can drift.

@havogt

havogt commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

I did not merge yet, because I want to do it after the release. Also together with possibly moving the build cache directory as well.

@havogt
havogt merged commit 3a6fa86 into main Aug 20, 2026
28 checks passed
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.

3 participants