Overview
Add support for Fastly's Core Cache API, providing advanced caching capabilities with request collapsing, stale-while-revalidate, and streaming.
WIT Interface
interface cache {
use types.{error};
use http-body.{body};
use http-req.{request};
use async-io.{pollable as pending-entry};
resource entry {
lookup: static func(key: list<u8>, options: lookup-options) -> result<entry, error>;
transaction-lookup: static func(key: list<u8>, options: lookup-options) -> result<entry, error>;
transaction-lookup-async: static func(key: list<u8>, options: lookup-options) -> result<pending-entry, error>;
transaction-insert: func(options: write-options) -> result<body, error>;
transaction-insert-and-stream-back: func(options: write-options) -> result<tuple<body, entry>, error>;
transaction-update: func(options: write-options) -> result<_, error>;
get-state: func() -> result<lookup-state, error>;
get-user-metadata: func(max-len: u64) -> result<option<list<u8>>, error>;
get-body: func(options: get-body-options) -> result<body, error>;
get-length: func() -> result<option<object-length>, error>;
get-max-age-ns: func() -> result<option<duration-ns>, error>;
get-stale-while-revalidate-ns: func() -> result<option<duration-ns>, error>;
get-age-ns: func() -> result<option<duration-ns>, error>;
get-hits: func() -> result<option<cache-hit-count>, error>;
transaction-cancel: func() -> result<_, error>;
}
resource replace-entry {
replace: static func(key: list<u8>, options: replace-options) -> result<replace-entry, error>;
get-age-ns: func() -> result<option<duration-ns>, error>;
get-body: func(options: get-body-options) -> result<option<body>, error>;
get-hits: func() -> result<option<cache-hit-count>, error>;
get-length: func() -> result<option<object-length>, error>;
get-max-age-ns: func() -> result<option<duration-ns>, error>;
get-stale-while-revalidate-ns: func() -> result<option<duration-ns>, error>;
get-state: func() -> result<option<lookup-state>, error>;
get-user-metadata: func(max-len: u64) -> result<option<list<u8>>, error>;
}
type object-length = u64;
type duration-ns = u64;
type cache-hit-count = u64;
resource extra-lookup-options {
constructor();
}
record lookup-options {
request-headers: option<borrow<request>>,
always-use-requested-range: bool,
extra: option<borrow<extra-lookup-options>>,
}
resource extra-write-options {
constructor();
}
record write-options {
max-age-ns: duration-ns,
request-headers: option<borrow<request>>,
vary-rule: option<string>,
initial-age-ns: option<duration-ns>,
stale-while-revalidate-ns: option<duration-ns>,
surrogate-keys: option<string>,
length: option<object-length>,
user-metadata: option<list<u8>>,
edge-max-age-ns: option<duration-ns>,
sensitive-data: bool,
extra: option<borrow<extra-write-options>>,
}
resource extra-get-body-options;
record get-body-options {
%from: option<u64>,
to: option<u64>,
extra: option<borrow<extra-get-body-options>>,
}
flags lookup-state {
found,
usable,
stale,
must-insert-or-update,
usable-if-error,
}
resource extra-replace-options {
constructor();
}
enum replace-strategy {
immediate,
immediate-force-miss,
wait,
}
record replace-options {
request-headers: option<borrow<request>>,
replace-strategy: option<replace-strategy>,
always-use-requested-range: bool,
extra: option<borrow<extra-replace-options>>,
}
insert: func(key: list<u8>, options: write-options) -> result<body, error>;
await-entry: func(handle: pending-entry) -> result<entry, error>;
close-pending-entry: func(handle: pending-entry) -> result<_, error>;
close-entry: func(handle: entry) -> result<_, error>;
replace-insert: func(handle: replace-entry, options: write-options) -> result<body, error>;
close-replace-entry: func(handle: replace-entry) -> result<_, error>;
}
WIT bindings: stubs/wit_world/imports/cache.py
API Design
- Implement
CacheEntry resource wrapper for cache operations
- Support lookup and transaction-based caching patterns
- Implement
LookupOptions and WriteOptions dataclasses
- Provide access to cache metadata: age, TTL, hits, state flags
- Transaction methods:
transaction_lookup(), insert(), update(), cancel()
- Entry body should implement
io.IOBase for streaming (similar to KV Store)
get_body() returns file-like object that can be read in chunks or passed to stdlib functions
Cross-SDK Comparison: All SDKs provide lookup(), insert(), transaction_lookup() with similar semantics. Rust uses strong typing for state/options enums, Go uses simple structs, JS uses async/Promise-based API. Python should support both blocking operations and context managers for transactions.
Viceroy Testing
Viceroy's cache implementation is limited/stubbed. Testing focus should be on:
- Verifying hostcall invocations work correctly
- Testing SDK wrapper logic (option parsing, state flag handling, error mapping)
- Ensuring body streaming integration functions properly
Do NOT:
- Try to verify actual cache persistence behavior
- Create elaborate tests around Viceroy's stubbed functionality
- Test cache hit/miss logic (this is host behavior, not SDK code)
The goal is to verify our Python wrapper code works, not to test Viceroy's cache implementation.
Reference
Overview
Add support for Fastly's Core Cache API, providing advanced caching capabilities with request collapsing, stale-while-revalidate, and streaming.
WIT Interface
WIT bindings:
stubs/wit_world/imports/cache.pyAPI Design
CacheEntryresource wrapper for cache operationsLookupOptionsandWriteOptionsdataclassestransaction_lookup(),insert(),update(),cancel()io.IOBasefor streaming (similar to KV Store)get_body()returns file-like object that can be read in chunks or passed to stdlib functionsCross-SDK Comparison: All SDKs provide
lookup(),insert(),transaction_lookup()with similar semantics. Rust uses strong typing for state/options enums, Go uses simple structs, JS uses async/Promise-based API. Python should support both blocking operations and context managers for transactions.Viceroy Testing
Viceroy's cache implementation is limited/stubbed. Testing focus should be on:
Do NOT:
The goal is to verify our Python wrapper code works, not to test Viceroy's cache implementation.
Reference