-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcache.py
More file actions
97 lines (65 loc) · 2.76 KB
/
Copy pathcache.py
File metadata and controls
97 lines (65 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""Cache policies for layered VM snapshots.
See docs/design/snapshots/2026-05-01-python-surface.md for the surface
and docs/design/snapshots/2026-05-01-data-model.md for the key formulas.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from datetime import timedelta
@dataclass(frozen=True)
class CachePolicy:
"""Base — never instantiate directly. Use the helpers below."""
@dataclass(frozen=True)
class CacheNone(CachePolicy):
"""Always run the step; never cache its snapshot.
Equivalent to today's behavior. Default for command steps.
"""
@dataclass(frozen=True)
class CacheForever(CachePolicy):
"""Cache forever, keyed only on (command, parent, env_keys).
Use for pure computations whose only inputs are visible to the planner.
DO NOT use for installs that fetch the public internet — package repos
drift; manual cache busts will be needed.
On a cache hit only SYSTEM state (the snapshot) is restored — files the
step wrote into the workspace are not replayed across runs; downstream
steps see the current run's source tree instead. Write build outputs to
system paths (e.g. ``/usr/local``) or use ``on_change`` if the step's
workspace outputs must survive cache hits.
"""
env_keys: tuple[str, ...] = ()
@dataclass(frozen=True)
class CacheTTL(CachePolicy):
"""Cache for `duration`; refresh once per window (UTC-midnight floored).
Two builds within the same UTC day share a key; a build at 00:30 UTC
the next day rebuilds.
"""
duration: timedelta
env_keys: tuple[str, ...] = ()
@dataclass(frozen=True)
class CacheOnChange(CachePolicy):
"""Rebuild whenever any file under `paths` changes.
Paths are relative to the source-archive root. File hashes are
computed at render time by `harmont.keygen` (paths are read from
the source archive's checkout root).
No `env_keys` field — file content already covers the invalidation
surface.
"""
paths: tuple[str, ...]
@dataclass(frozen=True)
class CacheCompose(CachePolicy):
"""Combine multiple policies. Cache hits ONLY when every sub-policy hits.
Useful for "rebuild daily OR when these files change":
CacheCompose(policies=(
CacheTTL(duration=timedelta(days=1)),
CacheOnChange(paths=("api/cabal.project",)),
))
"""
policies: tuple[CachePolicy, ...]
@dataclass(frozen=True)
class CachePredicate(CachePolicy):
"""Cache keyed on the return value of a user-supplied function.
The function is called at plan time. If it returns a different value
than the previous run, the cache key changes and the step re-runs.
"""
fn: object # Callable[[], str] — called at plan time