Class: Pikuri::UrlCache
- Inherits:
-
Object
- Object
- Pikuri::UrlCache
- Defined in:
- lib/pikuri/url_cache.rb
Overview
On-disk cache for string-keyed text payloads. The bundled tools use it to avoid re-fetching within a TTL: Tool::WebScrape.visit caches a URL's rendered Markdown, Tool::Search::Engines#search caches a query's result list (keys are SHA-256 hashed, so any opaque string works).
Each tool wires its own instance against a dedicated subdir under ROOT_DIR,
so a web_search query and a web_scrape URL can't collide on one file.
No global singleton — pass a fresh instance, or NULL to disable caching.
One file per entry (+rm -rf the directory to clear it.
Sharing: P_shared_benign — an instance holds only its TTL and directory,
and every tool that owns one holds it in a class-level constant, so all
agents (and other pikuri processes) hit the same files. If two callers race
on the same cold key, both compute and both write the same bytes — the
accepted tradeoff for keeping this a few dozen lines (worst case: a
duplicate fetch). The cross-agent flow is deliberate: a public URL's content
is nobody's private context.
Constant Summary collapse
- ROOT_DIR =
Root dir for per-tool cache subdirs, per XDG:
$XDG_CACHE_HOME/pikuri/url_cacheor~/.cache/pikuri/url_cache. Each tool picks its own subdir (+"#ROOT_DIR/web_scrape"+) so keys can't collide. Created lazily on first write. Paths.cache.join('url_cache').to_path
- DEFAULT_TTL =
Default freshness window: 2 hours. Long enough to cover an interactive session (revisiting a page or re-running a search within the working window hits the cache), short enough that resuming the next day doesn't serve stale results. (opencode caches nothing;
pi-web-fetchuses 15 min,pi-web-search5.) 2 * 60 * 60
- NULL =
Null cache: always misses, never persists — a drop-in for tests (or anywhere caching should be off) keeping the #fetch contract.
Object.new
Instance Method Summary collapse
-
#fetch(url) ⇒ String
Return the cached payload for
urlif fresh, else yield to compute it, persist, and return. -
#fresh?(path) ⇒ Boolean
True when
pathexists and was written within the TTL window. -
#initialize(ttl:, dir:) ⇒ UrlCache
constructor
A new instance of UrlCache.
-
#path_for(url) ⇒ String
Absolute path of the cache file for
url.
Constructor Details
#initialize(ttl:, dir:) ⇒ UrlCache
Returns a new instance of UrlCache.
47 48 49 50 |
# File 'lib/pikuri/url_cache.rb', line 47 def initialize(ttl:, dir:) @ttl = ttl @dir = dir end |
Instance Method Details
#fetch(url) ⇒ String
Return the cached payload for url if fresh, else yield to compute it,
persist, and return. The block runs only on a miss; if it raises, no file
is written (errors aren't cached).
59 60 61 62 63 64 65 66 67 |
# File 'lib/pikuri/url_cache.rb', line 59 def fetch(url) path = path_for(url) return File.read(path) if fresh?(path) content = yield FileUtils.mkdir_p(@dir) File.write(path, content) content end |
#fresh?(path) ⇒ Boolean
Returns true when path exists and was written within the
TTL window.
72 73 74 |
# File 'lib/pikuri/url_cache.rb', line 72 def fresh?(path) File.exist?(path) && Time.now - File.mtime(path) < @ttl end |
#path_for(url) ⇒ String
Returns absolute path of the cache file for url.
78 79 80 |
# File 'lib/pikuri/url_cache.rb', line 78 def path_for(url) File.join(@dir, "#{Digest::SHA256.hexdigest(url)}.txt") end |