Phase 7c+7d: cache invalidation + offline data layer
7c: Client data cache management via element attributes (sx-cache-invalidate) and response headers (SX-Cache-Invalidate, SX-Cache-Update). Programmatic API: invalidate-page-cache, invalidate-all-page-cache, update-page-cache. 7d: Service Worker (sx-sw.js) with IndexedDB for offline-capable data caching. Network-first for /sx/data/ and /sx/io/, stale-while- revalidate for /static/. Cache invalidation propagates from in-memory cache to SW via postMessage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -884,6 +884,9 @@ def auto_mount_pages(app: Any, service_name: str) -> None:
|
||||
# Mount IO proxy endpoint for Phase 5: client-side IO primitives
|
||||
mount_io_endpoint(app, service_name)
|
||||
|
||||
# Mount service worker at root scope for offline data layer
|
||||
mount_service_worker(app)
|
||||
|
||||
|
||||
def mount_pages(bp: Any, service_name: str,
|
||||
names: set[str] | list[str] | None = None) -> None:
|
||||
@@ -1186,3 +1189,39 @@ def mount_io_endpoint(app: Any, service_name: str) -> None:
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
logger.info("Mounted IO proxy for %s: %s", service_name, sorted(_ALLOWED_IO))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Service Worker mount
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
_SW_MOUNTED = False
|
||||
|
||||
def mount_service_worker(app: Any) -> None:
|
||||
"""Mount the SX service worker at /sx-sw.js (root scope).
|
||||
|
||||
The service worker provides offline data caching:
|
||||
- /sx/data/* and /sx/io/* responses cached in IndexedDB
|
||||
- /static/* assets cached via Cache API (stale-while-revalidate)
|
||||
- Everything else passes through to network
|
||||
"""
|
||||
global _SW_MOUNTED
|
||||
if _SW_MOUNTED:
|
||||
return
|
||||
_SW_MOUNTED = True
|
||||
|
||||
sw_path = os.path.join(
|
||||
os.path.dirname(__file__), "..", "static", "scripts", "sx-sw.js"
|
||||
)
|
||||
sw_path = os.path.abspath(sw_path)
|
||||
|
||||
async def serve_sw():
|
||||
from quart import send_file
|
||||
return await send_file(
|
||||
sw_path,
|
||||
mimetype="application/javascript",
|
||||
cache_timeout=0, # no caching — SW updates checked by browser
|
||||
)
|
||||
|
||||
app.add_url_rule("/sx-sw.js", endpoint="sx_service_worker", view_func=serve_sw)
|
||||
logger.info("Mounted service worker at /sx-sw.js")
|
||||
|
||||
Reference in New Issue
Block a user