Restore stashed WIP: live streaming plan, forms, CI pipeline, streaming demo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 22:07:59 +00:00
parent df1aa4e1d1
commit 5a68046bd8
21 changed files with 1463 additions and 120 deletions

View File

@@ -468,15 +468,16 @@
:sub-href "/isomorphism/"
:sub-nav (~section-nav :items isomorphism-nav-items :current "Streaming")
:selected "Streaming")
:fallback (div :class "p-8 space-y-4 animate-pulse"
(div :class "h-8 bg-stone-200 rounded w-1/3")
(div :class "h-4 bg-stone-200 rounded w-2/3")
(div :class "h-64 bg-stone-200 rounded"))
:shell (~streaming-demo-layout
(~suspense :id "stream-fast" :fallback (~stream-skeleton))
(~suspense :id "stream-medium" :fallback (~stream-skeleton))
(~suspense :id "stream-slow" :fallback (~stream-skeleton)))
:data (streaming-demo-data)
:content (~streaming-demo-content
:streamed-at streamed-at
:message message
:items items))
:content (~streaming-demo-chunk
:stream-label stream-label
:stream-color stream-color
:stream-message stream-message
:stream-time stream-time))
;; Wildcard must come AFTER specific routes (first-match routing)
(defpage isomorphism-page
@@ -534,6 +535,7 @@
"social-sharing" (~plan-social-sharing-content)
"sx-ci" (~plan-sx-ci-content)
"cssx-components" (~plan-cssx-components-content)
"live-streaming" (~plan-live-streaming-content)
:else (~plans-index-content)))
;; ---------------------------------------------------------------------------

View File

@@ -838,19 +838,40 @@ def _data_test_data() -> dict:
}
async def _streaming_demo_data() -> dict:
"""Simulate slow IO for streaming demo — 1.5s delay."""
async def _streaming_demo_data():
"""Multi-stream demo — yields three chunks at staggered intervals.
Each yield is a dict with _stream_id (matching a ~suspense :id in the
shell) plus bindings for the :content expression. The streaming
infrastructure detects the async generator and resolves each suspense
placeholder as each chunk arrives.
"""
import asyncio
await asyncio.sleep(1.5)
from datetime import datetime, timezone
return {
"streamed-at": datetime.now(timezone.utc).isoformat(timespec="seconds"),
"message": "This content was streamed after a 1.5 second delay.",
"items": [
{"label": "Shell", "detail": "HTML shell with suspense placeholders sent immediately"},
{"label": "Bootstrap", "detail": "sx-browser.js loads, renders fallback skeletons"},
{"label": "IO Start", "detail": "Data fetch and header fetch run concurrently"},
{"label": "Resolve", "detail": "As each IO completes, <script> chunk replaces placeholder"},
{"label": "Done", "detail": "Page fully rendered — all suspense resolved"},
],
await asyncio.sleep(1)
yield {
"stream-id": "stream-fast",
"stream-label": "Fast API",
"stream-color": "green",
"stream-message": "Responded in ~1 second",
"stream-time": datetime.now(timezone.utc).isoformat(timespec="seconds"),
}
await asyncio.sleep(2) # 3s total
yield {
"stream-id": "stream-medium",
"stream-label": "Database Query",
"stream-color": "blue",
"stream-message": "Query completed in ~3 seconds",
"stream-time": datetime.now(timezone.utc).isoformat(timespec="seconds"),
}
await asyncio.sleep(2) # 5s total
yield {
"stream-id": "stream-slow",
"stream-label": "ML Inference",
"stream-color": "amber",
"stream-message": "Model inference completed in ~5 seconds",
"stream-time": datetime.now(timezone.utc).isoformat(timespec="seconds"),
}