Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions context/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ This file tracks agent decisions, architectural changes, and context for future

---

## [2026-09-14] — ProxyWasm cache module

### Overview
Added `fastedge::proxywasm::cache` — the ProxyWasm/CDN counterpart of the `cache-sync` WIT interface already exposed to HTTP apps as `fastedge::cache`.

### Decisions
- Free functions rather than a handle-based `Store` (as in `key_value`): the `cache-sync` WIT interface has no named stores or handles, every operation is scoped to the calling app and addressed by key alone.
- `Error` mirrors the WIT `cache-types.error` variant (`AccessDenied`, `InternalError`, `Other(String)`) instead of reusing `key_value::Error` (which carries `NoSuchStore`).
- `option<u64>` TTL is carried over FFI as a plain `u64` with `0` meaning "no expiry", avoiding an extra flag/pointer parameter for a value that has no meaningful zero case.
- Host status codes follow the real ProxyWasm status enum (`0` ok, `1` not found, `2` bad argument — which also carries access denial, as in `key_value` — `10` internal failure); "not found" is folded into `Ok(None)` / `Ok(false)` / no-op per the WIT contract. Note `reference/ERROR_CODES.md` previously listed `3`/`6` for these, which does not match the host enum; corrected in the same change.

### Changes
- `src/proxywasm/cache.rs` — new module: `get`, `set`, `delete`, `exists`, `incr`, `expire`, `purge`, `purge_prefix`
- `src/proxywasm/mod.rs` — `pub mod cache`, eight `proxy_cache_*` FFI declarations, module docs
- `context/architecture/HOST_SDK_CONTRACT.md` — documented the `proxy_cache_*` FFI functions
- `examples/cdn/cache/` — new CDN example exercising all eight operations via query parameters, modelled on `examples/cdn/key_value/` (no `store` param — the cache has no named stores)
- `examples/README.md` — listed the new CDN example
- `fastedge-plugin-source/manifest.json` — `cdn-cache-blueprint` / `cdn-cache-pattern` source + target entries

### Follow-up
- The `proxy_cache_*` symbol names and signatures were derived from the existing `proxy_kv_store_*` convention — they must be confirmed against the host implementation before release.
- `examples/cdn/cache/Cargo.toml` uses a path dependency (`fastedge = { path = "../../.." }`) because `proxywasm::cache` is not in the published 0.4.2 crate. Every other example uses the registry dep — switch this one to `{ version = "0.4", features = ["proxywasm"] }` once the module is published.
- Per `context/PLUGIN_CONTRACT.md` steps 3-4, the `fastedge-plugin` repo still needs intent files (`cdn/cache-rust.md`, `cdn/examples-cache-rust.md`) and placeholder reference files at the mapped target paths, or the next sync will fail for the two new manifest entries.

---

## [2026-04-07] — Migrated Rust examples from FastEdge-examples

### Overview
Expand Down
16 changes: 16 additions & 0 deletions context/architecture/HOST_SDK_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ These are the `extern "C"` functions the host makes available to WASM modules. T
| `proxy_kv_store_zscan(handle, key, len, pattern, plen, ret, ret_len)` | `Store::zscan(key, pattern)` | Sorted set pattern scan |
| `proxy_kv_store_bf_exists(handle, key, len, item, ilen, ret)` | `Store::bf_exists(key, item)` | Bloom filter membership check |

### Cache

| FFI Function | SDK Wrapper | Purpose |
|-------------|-------------|---------|
| `proxy_cache_get(key, len, ret, ret_len)` | `cache::get(key)` | Retrieve cached value by key |
| `proxy_cache_set(key, len, value, vlen, ttl_ms)` | `cache::set(key, value, ttl)` | Store value; `ttl_ms = 0` means no expiry |
| `proxy_cache_delete(key, len)` | `cache::delete(key)` | Delete a cached key (no-op if absent) |
| `proxy_cache_exists(key, len, ret)` | `cache::exists(key)` | Key membership check |
| `proxy_cache_incr(key, len, delta, ret)` | `cache::incr(key, delta)` | Atomic integer increment/decrement |
| `proxy_cache_expire(key, len, ttl_ms, ret)` | `cache::expire(key, ttl)` | Set/update key expiry |
| `proxy_cache_purge(ret)` | `cache::purge()` | Delete all of the app's cached keys |
| `proxy_cache_purge_prefix(prefix, len, ret)` | `cache::purge_prefix(prefix)` | Delete the app's keys matching a prefix |

The cache has no handle — every operation is scoped to the calling application and addressed by key alone. Mirrors the `cache-sync` WIT interface used by HTTP apps.

### Secrets

| FFI Function | SDK Wrapper | Purpose |
Expand Down Expand Up @@ -86,6 +101,7 @@ For the WIT-based Component Model path, the same capabilities are exposed as typ
The WIT world (`gcore:fastedge/reactor`) imports:
- `http` + `http-client` — request/response types and outbound HTTP
- `key-value` — persistent storage (same operations as FFI above)
- `cache-sync` — ephemeral cache (same operations as FFI above)
- `secret` — encrypted secrets (same operations as FFI above)
- `dictionary` — read-only config (same as FFI above)
- `utils` — diagnostics (same as FFI above)
Expand Down
21 changes: 18 additions & 3 deletions context/reference/ERROR_CODES.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ These typically surface when:
| `AccessDenied` | App doesn't have permission to access this store |
| `InternalError` | Platform-side storage error |

### Cache (`cache::Error`)

| Variant | Meaning |
|---------|---------|
| `AccessDenied` | App doesn't have permission to use the cache — check that the app's cache mode is enabled |
| `InternalError` | Platform-side cache error |
| `Other(String)` | Unrecognized host status code |

### Secrets (`secret::Error`)

| Variant | Meaning |
Expand All @@ -89,9 +97,16 @@ The `proxy_*` FFI functions return `u32` status codes:
|-------|---------|
| `0` | Success |
| `1` | Not found (key doesn't exist) |
| `2` | Bad argument |
| `3` | Not allowed |
| `6` | Internal failure |
| `2` | Bad argument — also how the host reports access denial |
| `3` | Serialization failure |
| `4` | Parse failure |
| `6` | Invalid memory access |
| `7` | Empty |
| `8` | CAS mismatch |
| `10` | Internal failure |
| `12` | Unimplemented |

These are the values of the host's `ProxyStatus` enum (`fastedge_proxywasm::v2::ProxyStatus`) — the authoritative list lives there, not here.

The SDK's ProxyWasm wrappers in `src/proxywasm/` translate these into Rust `Result` types — application code doesn't see raw status codes.

Expand Down
Loading
Loading