From e2562b5a0bef9f82a686a13865940b592ed423bc Mon Sep 17 00:00:00 2001 From: RobertClarke Date: Thu, 16 Jul 2026 18:34:52 -0400 Subject: [PATCH 1/3] Cache settlement artifact responses --- .env.example | 2 ++ compose.yaml | 2 ++ docs/public-dashboard-api/README.md | 7 +++++-- lab/prism/public_api.py | 10 ++++++++++ tests/test_prism_compose_profile.py | 2 ++ tests/test_prism_public_dashboard_api.py | 9 +++++++++ 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index f47b694..2c0508b 100644 --- a/.env.example +++ b/.env.example @@ -196,6 +196,8 @@ PRISM_PUBLIC_CACHE_TTL_SECONDS=5 PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS=300 PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS=3600 +PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS=300 +PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS=86400 PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=86400 PRISM_PUBLIC_CACHE_MAX_ENTRIES=512 diff --git a/compose.yaml b/compose.yaml index 0dd31a2..b2184b4 100644 --- a/compose.yaml +++ b/compose.yaml @@ -523,6 +523,8 @@ services: PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS:-300} PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-3600} + PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS:-300} + PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS:-86400} PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-86400} PRISM_PUBLIC_CACHE_MAX_ENTRIES: ${PRISM_PUBLIC_CACHE_MAX_ENTRIES:-512} diff --git a/docs/public-dashboard-api/README.md b/docs/public-dashboard-api/README.md index dbb2cc8..8695040 100644 --- a/docs/public-dashboard-api/README.md +++ b/docs/public-dashboard-api/README.md @@ -39,8 +39,9 @@ emits conservative browser caching (`Cache-Control: public, max-age=0, must-revalidate`) plus shared-cache headers for CDNs such as Vercel. Dynamic dashboard read models default to a 5-second shared-cache TTL with 30 seconds of `stale-while-revalidate`. `GET /public/v1/mining-configuration` defaults to 300 -seconds, and content-addressed artifact routes default to 86400 seconds with an -immutable shared-cache hint. +seconds, settlement-artifact manifests default to 300 seconds, and +content-addressed artifact routes default to 86400 seconds with an immutable +shared-cache hint. Operators can tune the defaults with: @@ -49,6 +50,8 @@ Operators can tune the defaults with: - `PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS` - `PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS` - `PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS` +- `PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS` +- `PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS` - `PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS` - `PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS` - `PRISM_PUBLIC_CACHE_MAX_ENTRIES` diff --git a/lab/prism/public_api.py b/lab/prism/public_api.py index 12be27d..91cdbe4 100644 --- a/lab/prism/public_api.py +++ b/lab/prism/public_api.py @@ -196,6 +196,16 @@ def public_cache_policy(path: str) -> PublicCachePolicy: 3600, ), ) + if path.startswith("/public/v1/blocks/") and path.endswith("/settlement-artifacts"): + block_hash = path[len("/public/v1/blocks/"):-len("/settlement-artifacts")].strip() + if _is_hex64(block_hash): + return PublicCachePolicy( + ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS", 300), + stale_while_revalidate_seconds=env_nonnegative_int( + "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS", + 30, + ), + ) if path.startswith("/public/v1/artifacts/"): return PublicCachePolicy( ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS", 86400), diff --git a/tests/test_prism_compose_profile.py b/tests/test_prism_compose_profile.py index 022fffb..20c0087 100644 --- a/tests/test_prism_compose_profile.py +++ b/tests/test_prism_compose_profile.py @@ -172,6 +172,8 @@ def test_prism_coordinator_gets_required_environment(self) -> None: self.assertEqual(env["PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS"], "300") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "3600") + self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS"], "300") + self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS"], "86400") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "86400") self.assertEqual(env["PRISM_PUBLIC_CACHE_MAX_ENTRIES"], "512") diff --git a/tests/test_prism_public_dashboard_api.py b/tests/test_prism_public_dashboard_api.py index 10e612e..49a2d72 100644 --- a/tests/test_prism_public_dashboard_api.py +++ b/tests/test_prism_public_dashboard_api.py @@ -844,6 +844,8 @@ def test_public_api_cache_headers_use_route_specific_ttls(self) -> None: os.environ, { "PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS": "600", + "PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS": "900", + "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS": "120", "PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS": "7200", }, clear=True, @@ -854,6 +856,12 @@ def test_public_api_cache_headers_use_route_specific_ttls(self) -> None: ) as config_response: json.loads(config_response.read()) config_cache = config_response.headers.get("CDN-Cache-Control") + with urllib.request.urlopen( + f"http://127.0.0.1:{server.server_port}/public/v1/blocks/{ledger.block_hash}/settlement-artifacts", + timeout=5, + ) as settlement_response: + json.loads(settlement_response.read()) + settlement_cache = settlement_response.headers.get("CDN-Cache-Control") with urllib.request.urlopen( f"http://127.0.0.1:{server.server_port}/public/v1/artifacts/{ledger.audit_bundle_sha256}", timeout=5, @@ -866,6 +874,7 @@ def test_public_api_cache_headers_use_route_specific_ttls(self) -> None: thread.join(timeout=5) self.assertEqual(config_cache, "public, max-age=600, stale-while-revalidate=3600") + self.assertEqual(settlement_cache, "public, max-age=900, stale-while-revalidate=120") self.assertEqual(artifact_cache, "public, max-age=7200, stale-while-revalidate=86400, immutable") def test_public_api_errors_use_public_error_schema(self) -> None: From a7c80ee7a8b49f8238a480268057d7d6b78b388b Mon Sep 17 00:00:00 2001 From: RobertClarke Date: Thu, 16 Jul 2026 18:43:20 -0400 Subject: [PATCH 2/3] Keep settlement response cache short --- .env.example | 2 +- compose.yaml | 2 +- docs/public-dashboard-api/README.md | 6 +++--- lab/prism/public_api.py | 2 +- tests/test_prism_compose_profile.py | 2 +- tests/test_prism_public_dashboard_api.py | 15 ++++++++++++--- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.env.example b/.env.example index 2c0508b..1ce152d 100644 --- a/.env.example +++ b/.env.example @@ -196,7 +196,7 @@ PRISM_PUBLIC_CACHE_TTL_SECONDS=5 PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS=300 PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS=3600 -PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS=300 +PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS=5 PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS=86400 PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=86400 diff --git a/compose.yaml b/compose.yaml index b2184b4..c010be6 100644 --- a/compose.yaml +++ b/compose.yaml @@ -523,7 +523,7 @@ services: PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS:-300} PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-3600} - PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS:-300} + PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS:-5} PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS:-86400} PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-86400} diff --git a/docs/public-dashboard-api/README.md b/docs/public-dashboard-api/README.md index 8695040..fc1f9b6 100644 --- a/docs/public-dashboard-api/README.md +++ b/docs/public-dashboard-api/README.md @@ -39,9 +39,9 @@ emits conservative browser caching (`Cache-Control: public, max-age=0, must-revalidate`) plus shared-cache headers for CDNs such as Vercel. Dynamic dashboard read models default to a 5-second shared-cache TTL with 30 seconds of `stale-while-revalidate`. `GET /public/v1/mining-configuration` defaults to 300 -seconds, settlement-artifact manifests default to 300 seconds, and -content-addressed artifact routes default to 86400 seconds with an immutable -shared-cache hint. +seconds. Settlement-artifact responses also default to 5 seconds because they +include live fanout status and broadcast attempts. Content-addressed artifact +routes default to 86400 seconds with an immutable shared-cache hint. Operators can tune the defaults with: diff --git a/lab/prism/public_api.py b/lab/prism/public_api.py index 91cdbe4..9d69cea 100644 --- a/lab/prism/public_api.py +++ b/lab/prism/public_api.py @@ -200,7 +200,7 @@ def public_cache_policy(path: str) -> PublicCachePolicy: block_hash = path[len("/public/v1/blocks/"):-len("/settlement-artifacts")].strip() if _is_hex64(block_hash): return PublicCachePolicy( - ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS", 300), + ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS", 5), stale_while_revalidate_seconds=env_nonnegative_int( "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS", 30, diff --git a/tests/test_prism_compose_profile.py b/tests/test_prism_compose_profile.py index 20c0087..351ad66 100644 --- a/tests/test_prism_compose_profile.py +++ b/tests/test_prism_compose_profile.py @@ -172,7 +172,7 @@ def test_prism_coordinator_gets_required_environment(self) -> None: self.assertEqual(env["PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS"], "300") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "3600") - self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS"], "300") + self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS"], "5") self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS"], "86400") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "86400") diff --git a/tests/test_prism_public_dashboard_api.py b/tests/test_prism_public_dashboard_api.py index 49a2d72..038b4e0 100644 --- a/tests/test_prism_public_dashboard_api.py +++ b/tests/test_prism_public_dashboard_api.py @@ -844,8 +844,8 @@ def test_public_api_cache_headers_use_route_specific_ttls(self) -> None: os.environ, { "PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS": "600", - "PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS": "900", - "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS": "120", + "PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS": "15", + "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS": "10", "PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS": "7200", }, clear=True, @@ -874,9 +874,18 @@ def test_public_api_cache_headers_use_route_specific_ttls(self) -> None: thread.join(timeout=5) self.assertEqual(config_cache, "public, max-age=600, stale-while-revalidate=3600") - self.assertEqual(settlement_cache, "public, max-age=900, stale-while-revalidate=120") + self.assertEqual(settlement_cache, "public, max-age=15, stale-while-revalidate=10") self.assertEqual(artifact_cache, "public, max-age=7200, stale-while-revalidate=86400, immutable") + def test_settlement_artifact_cache_default_stays_short_for_live_status(self) -> None: + path = f"/public/v1/blocks/{FakePublicLedger.block_hash}/settlement-artifacts" + + with patch.dict(os.environ, {}, clear=True): + policy = public_api.public_cache_policy(path) + + self.assertEqual(policy.ttl_seconds, 5) + self.assertEqual(policy.stale_while_revalidate_seconds, 30) + def test_public_api_errors_use_public_error_schema(self) -> None: with self.assertRaises(urllib.error.HTTPError) as raised: self.get_json("/public/v1/leaderboard?window=24h") From 2e83db7d43828f30ec18f0bbd2c6759d812376a2 Mon Sep 17 00:00:00 2001 From: RobertClarke Date: Thu, 16 Jul 2026 18:57:08 -0400 Subject: [PATCH 3/3] Preserve global settlement cache overrides --- .env.example | 4 ++-- compose.yaml | 4 ++-- docs/public-dashboard-api/README.md | 5 +++++ lab/prism/public_api.py | 19 ++++++++++++------- tests/test_prism_compose_profile.py | 4 ++-- tests/test_prism_public_dashboard_api.py | 16 ++++++++++++++++ 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/.env.example b/.env.example index 1ce152d..3ae48a3 100644 --- a/.env.example +++ b/.env.example @@ -196,8 +196,8 @@ PRISM_PUBLIC_CACHE_TTL_SECONDS=5 PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS=300 PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS=3600 -PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS=5 -PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=30 +PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS= +PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS= PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS=86400 PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS=86400 PRISM_PUBLIC_CACHE_MAX_ENTRIES=512 diff --git a/compose.yaml b/compose.yaml index c010be6..8dd2baa 100644 --- a/compose.yaml +++ b/compose.yaml @@ -523,8 +523,8 @@ services: PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS:-300} PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-3600} - PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS:-5} - PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-30} + PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS:-} + PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-} PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS:-86400} PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS: ${PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS:-86400} PRISM_PUBLIC_CACHE_MAX_ENTRIES: ${PRISM_PUBLIC_CACHE_MAX_ENTRIES:-512} diff --git a/docs/public-dashboard-api/README.md b/docs/public-dashboard-api/README.md index fc1f9b6..bde80d3 100644 --- a/docs/public-dashboard-api/README.md +++ b/docs/public-dashboard-api/README.md @@ -43,6 +43,11 @@ seconds. Settlement-artifact responses also default to 5 seconds because they include live fanout status and broadcast attempts. Content-addressed artifact routes default to 86400 seconds with an immutable shared-cache hint. +Settlement-specific cache controls are blank by default and inherit +`PRISM_PUBLIC_CACHE_TTL_SECONDS` and +`PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS`. Set them only when an +explicit route-specific override is required. + Operators can tune the defaults with: - `PRISM_PUBLIC_CACHE_ENABLED` diff --git a/lab/prism/public_api.py b/lab/prism/public_api.py index 9d69cea..d345639 100644 --- a/lab/prism/public_api.py +++ b/lab/prism/public_api.py @@ -188,6 +188,11 @@ def public_cache_key(path: str, query: dict[str, list[str]]) -> tuple[str, tuple def public_cache_policy(path: str) -> PublicCachePolicy: if not env_bool("PRISM_PUBLIC_CACHE_ENABLED", default=True): return PublicCachePolicy(ttl_seconds=0, stale_while_revalidate_seconds=0) + dynamic_ttl_seconds = env_nonnegative_int("PRISM_PUBLIC_CACHE_TTL_SECONDS", 5) + dynamic_stale_while_revalidate_seconds = env_nonnegative_int( + "PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS", + 30, + ) if path == "/public/v1/mining-configuration": return PublicCachePolicy( ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS", 300), @@ -200,10 +205,13 @@ def public_cache_policy(path: str) -> PublicCachePolicy: block_hash = path[len("/public/v1/blocks/"):-len("/settlement-artifacts")].strip() if _is_hex64(block_hash): return PublicCachePolicy( - ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS", 5), + ttl_seconds=env_nonnegative_int( + "PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS", + dynamic_ttl_seconds, + ), stale_while_revalidate_seconds=env_nonnegative_int( "PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS", - 30, + dynamic_stale_while_revalidate_seconds, ), ) if path.startswith("/public/v1/artifacts/"): @@ -216,11 +224,8 @@ def public_cache_policy(path: str) -> PublicCachePolicy: immutable=True, ) return PublicCachePolicy( - ttl_seconds=env_nonnegative_int("PRISM_PUBLIC_CACHE_TTL_SECONDS", 5), - stale_while_revalidate_seconds=env_nonnegative_int( - "PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS", - 30, - ), + ttl_seconds=dynamic_ttl_seconds, + stale_while_revalidate_seconds=dynamic_stale_while_revalidate_seconds, ) diff --git a/tests/test_prism_compose_profile.py b/tests/test_prism_compose_profile.py index 351ad66..f9e3d0b 100644 --- a/tests/test_prism_compose_profile.py +++ b/tests/test_prism_compose_profile.py @@ -172,8 +172,8 @@ def test_prism_coordinator_gets_required_environment(self) -> None: self.assertEqual(env["PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_TTL_SECONDS"], "300") self.assertEqual(env["PRISM_PUBLIC_CONFIG_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "3600") - self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS"], "5") - self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "30") + self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_TTL_SECONDS"], "") + self.assertEqual(env["PRISM_PUBLIC_SETTLEMENT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_TTL_SECONDS"], "86400") self.assertEqual(env["PRISM_PUBLIC_ARTIFACT_CACHE_STALE_WHILE_REVALIDATE_SECONDS"], "86400") self.assertEqual(env["PRISM_PUBLIC_CACHE_MAX_ENTRIES"], "512") diff --git a/tests/test_prism_public_dashboard_api.py b/tests/test_prism_public_dashboard_api.py index 038b4e0..f950c5d 100644 --- a/tests/test_prism_public_dashboard_api.py +++ b/tests/test_prism_public_dashboard_api.py @@ -886,6 +886,22 @@ def test_settlement_artifact_cache_default_stays_short_for_live_status(self) -> self.assertEqual(policy.ttl_seconds, 5) self.assertEqual(policy.stale_while_revalidate_seconds, 30) + def test_settlement_artifact_cache_inherits_global_overrides(self) -> None: + path = f"/public/v1/blocks/{FakePublicLedger.block_hash}/settlement-artifacts" + + with patch.dict( + os.environ, + { + "PRISM_PUBLIC_CACHE_TTL_SECONDS": "0", + "PRISM_PUBLIC_CACHE_STALE_WHILE_REVALIDATE_SECONDS": "7", + }, + clear=True, + ): + policy = public_api.public_cache_policy(path) + + self.assertEqual(policy.ttl_seconds, 0) + self.assertEqual(policy.stale_while_revalidate_seconds, 7) + def test_public_api_errors_use_public_error_schema(self) -> None: with self.assertRaises(urllib.error.HTTPError) as raised: self.get_json("/public/v1/leaderboard?window=24h")