Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c56ff74
Add opt-in reusable sandbox lifecycle for the Fastly adapter
prk-Jr Sep 17, 2026
00c4e42
Move script accumulation buffers into per-document state
prk-Jr Sep 17, 2026
ca7e7fa
Retain the built application across requests in a reused sandbox
prk-Jr Sep 17, 2026
f51ba6f
Report vCPU and heap counters, and record the local A/B/C results
prk-Jr Sep 17, 2026
0b447f8
Test the real build decision, and tighten the measurement claims
prk-Jr Sep 17, 2026
dd74fa2
Build the console output module on every host target
prk-Jr Sep 17, 2026
66529f8
Warn on an unreliable probe run
prk-Jr Sep 17, 2026
b6df0b3
Pin EdgeZero to the reusable-app-lifecycle revision
prk-Jr Sep 17, 2026
281c89a
Adopt EdgeZero lifecycle helpers for custom Fastly dispatch
prk-Jr Sep 17, 2026
52942ba
Fix final initialization count in sandbox retirement logs
prk-Jr Sep 17, 2026
dd2e931
Gate the counters endpoint on its feature alone
prk-Jr Sep 17, 2026
385853b
Update EdgeZero reusable lifecycle revision
prk-Jr Sep 19, 2026
17f80ae
Update EdgeZero to Cloudflare test import fix
prk-Jr Sep 19, 2026
ea7c450
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Sep 21, 2026
ad4e4d2
Harden reusable sandbox metrics and limits
prk-Jr Sep 21, 2026
868a2c9
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Sep 21, 2026
d133495
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Sep 22, 2026
455ba89
Drop the duplicate request count from the sandbox counters endpoint
prk-Jr Sep 22, 2026
147655e
Merge branch '856-fastly-reusable-sandbox' of github.com-prkjr:IABTec…
prk-Jr Sep 22, 2026
47df3d6
Clarify sandbox probe prerequisites and release guidance
prk-Jr Sep 24, 2026
037fd5a
Merge main and reconcile document-scoped script state
prk-Jr Sep 24, 2026
03def0a
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Oct 1, 2026
3fc5f06
Clarify reusable sandbox rewrite state
prk-Jr Oct 1, 2026
44bcbc4
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Oct 1, 2026
75d218a
Update EdgeZero to the reviewed lifecycle revision
prk-Jr Oct 2, 2026
cf31f66
Merge branch 'main' into 856-fastly-reusable-sandbox
prk-Jr Oct 4, 2026
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
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ build-fastly = "build -p trusted-server-core -p trusted-server-adapter-fastly -p
check-fastly = "check -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --target wasm32-wasip1"
clippy-fastly = "clippy -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --all-targets --all-features --target wasm32-wasip1 -- -D warnings"
test-fastly = "test -p trusted-server-core -p trusted-server-adapter-fastly -p trusted-server-js -p trusted-server-openrtb --target wasm32-wasip1"
# Feature-on counterpart of `test-fastly`. `test-fastly` does NOT pass
# --all-features, so without this the reusable-sandbox code is linted by
# `clippy-fastly` but its tests never execute.
test-fastly-reuse = "test -p trusted-server-adapter-fastly --target wasm32-wasip1 --features reusable-sandbox"

# --- Axum adapter (native dev server) ---
build-axum = "build -p trusted-server-adapter-axum"
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ jobs:
- name: Run tests
run: cargo test-fastly

- name: Run tests (reusable-sandbox feature)
run: cargo test-fastly-reuse

- name: Run template cache ESI local harness
run: BID_DELAY=3 ./scripts/template-cache-local-test.sh esi

Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ spin up --from crates/trusted-server-adapter-spin
# See .cargo/config.toml; default-members = [fastly] so Viceroy can locate
# the binary via `cargo run --bin`.
cargo test-fastly # Fastly adapter + core (wasm32-wasip1 via Viceroy)
cargo test-fastly-reuse # Fastly adapter with the reusable-sandbox feature on
cargo test-axum # Axum dev server adapter (native)
cargo test-cloudflare # Cloudflare Workers adapter (native host)
cargo test-spin # Spin adapter route tests (native host)
Expand Down Expand Up @@ -346,7 +347,7 @@ Every PR must pass:

1. `cargo fmt --all -- --check`
2. `cargo clippy-fastly && cargo clippy-axum && cargo clippy-cloudflare && cargo clippy-cloudflare-wasm && cargo clippy-spin-native && cargo clippy-spin-wasm && cargo clippy-cli && cargo clippy-codegen`
3. `cargo test-fastly && cargo test-axum && cargo test-cloudflare && cargo test-spin`
3. `cargo test-fastly && cargo test-fastly-reuse && cargo test-axum && cargo test-cloudflare && cargo test-spin`
4. `cargo test --manifest-path crates/trusted-server-integration-tests/Cargo.toml --test parity`
5. JS build and test (`cd crates/trusted-server-js/lib && npx vitest run`)
6. JS format (`cd crates/trusted-server-js/lib && npm run format`)
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ cssparser = "0.36"
derive_more = { version = "2.0", features = ["display", "error"] }
directories = "5"
ed25519-dalek = { version = "2.2", features = ["rand_core"] }
edgezero-adapter-axum = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8", default-features = false }
edgezero-adapter-cloudflare = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8", default-features = false }
edgezero-adapter-fastly = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8", default-features = false }
edgezero-adapter-spin = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8", default-features = false }
edgezero-cli = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8" }
edgezero-core = { git = "https://github.com/stackpop/edgezero", tag = "v0.0.8", default-features = false }
edgezero-adapter-axum = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373", default-features = false }
edgezero-adapter-cloudflare = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373", default-features = false }
edgezero-adapter-fastly = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373", default-features = false }
Comment thread
aram356 marked this conversation as resolved.
edgezero-adapter-spin = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373", default-features = false }
edgezero-cli = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373" }
edgezero-core = { git = "https://github.com/stackpop/edgezero", rev = "35a72835322fe0127beb2ce998e4988e95974373", default-features = false }
env_logger = "0.11"
error-stack = "0.6"
esi = "0.7.2"
Expand Down
7 changes: 7 additions & 0 deletions crates/trusted-server-adapter-fastly/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ version = { workspace = true }
[lints]
workspace = true

[features]
# Opt-in reusable sandbox lifecycle. Off by default, and `fastly.toml`'s build
# command does not pass it, so production builds keep the single-request entry
# point. Enabling the feature alone does not enable reuse: the bounds still
# come from the runtime environment (see `sandbox::resolve_mode`).
reusable-sandbox = []

[dependencies]
async-trait = { workspace = true }
base64 = { workspace = true }
Expand Down
6 changes: 4 additions & 2 deletions crates/trusted-server-adapter-fastly/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,10 @@ impl RuntimeStoreConfig {

/// Application state built once per Wasm instance and shared for its lifetime.
///
/// In Fastly Compute each request spawns a new Wasm instance, so this struct is
/// effectively per-request. It holds pre-parsed settings and all service handles.
/// By default Fastly serves one request per instance. With the opt-in reusable
/// sandbox feature and complete runtime bounds, a successful application build
/// retains this state across requests until the sandbox retires. Settings and
/// shared services live here; request-specific state must remain request-local.
pub(crate) struct AppState {
pub(crate) settings: Arc<Settings>,
pub(crate) orchestrator: Arc<AuctionOrchestrator>,
Expand Down
22 changes: 16 additions & 6 deletions crates/trusted-server-adapter-fastly/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,21 @@ fn detect_max_level(explicit: Option<&str>, hostname: Option<&str>) -> log::Leve
/// used as-is, so `error`/`off` lowers it just as `debug` raises it; see
/// [`resolve_max_level`].
///
/// # Panics
/// # Errors
///
/// Panics if the Fastly logger cannot be built or if the global logger has already
/// been set.
pub(crate) fn init_logger() {
/// Returns a message if the Fastly logger cannot be built or if a global
/// logger is already installed. Returning rather than panicking lets
/// `Sandbox::setup_once` mark setup complete only on success, which *allows*
/// a later callback to retry. It does not by itself make retrying safe:
/// `setup_once` does not roll back partial side effects, so repeating this
/// function must stay harmless.
///
/// It is, for the two ways it can fail. A failed `Logger::builder().build()`
/// installs nothing. A failed `fern::Dispatch::apply()` means a global logger
/// is already installed, so the retry fails the same way and never installs a
/// second one; the only repeated side effect is constructing a `Logger` that
/// is then dropped. Neither path leaves the process partially configured.
pub(crate) fn init_logger() -> Result<(), String> {
let explicit = std::env::var(LOG_LEVEL_ENV).ok();
let hostname = std::env::var(LOCAL_HOSTNAME_ENV).ok();
let max_level = detect_max_level(explicit.as_deref(), hostname.as_deref());
Expand All @@ -88,7 +98,7 @@ pub(crate) fn init_logger() {
.echo_stdout(true)
.max_level(max_level)
.build()
.expect("should build Logger");
.map_err(|e| format!("should build Logger: {e}"))?;

fern::Dispatch::new()
.level(max_level)
Expand All @@ -103,7 +113,7 @@ pub(crate) fn init_logger() {
})
.chain(Box::new(logger) as Box<dyn log::Log>)
.apply()
.expect("should initialize logger");
.map_err(|e| format!("should initialize logger: {e}"))
}

#[cfg(test)]
Expand Down
Loading
Loading