Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 16s
Blog posts now live in the durable SX store (persist/durable-backend, on-disk under $SX_PERSIST_DIR — already built: sx_persist_store.ml + lib/persist/ durable.sx). Publishing appends insert ops to the slug's content stream; posts survive restarts (verified: seq/log stable across container restart, re-seed idempotent). Read path: http-listen handlers can't drive per-request perform/IO (sx_call doesn't resolve the CEK IO suspension the way the main loop does), so posts are materialised from the store into an in-memory view at boot (host/blog-load-all! + host/blog-seed!) and request handlers read the view — perform-free. Store is source of truth; view is a boot-rebuilt cache. Deploy: docker-compose.dev-sx-host.yml mounts /root/sx-host-persist (chowned to appuser 10001) at /data/persist; SX_PERSIST_DIR set. blog.rose-ash.com/welcome/ live. Per-request-IO kernel fix tracked in the plan as the next task. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
122 lines
4.1 KiB
Bash
Executable File
122 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# host-on-sx live server launcher. Loads the kernel stdlib, the subsystem
|
|
# libraries, and the host modules into one sx_server process, then calls
|
|
# (host/serve PORT ...) which binds the native http-listen server to the
|
|
# Dream-shaped host app. Runs in the FOREGROUND (http-listen blocks), so this
|
|
# doubles as a container entrypoint and a local launcher.
|
|
#
|
|
# Usage:
|
|
# bash lib/host/serve.sh # serve on $HOST_PORT (default 8910)
|
|
# HOST_PORT=8920 bash lib/host/serve.sh # pick a port
|
|
#
|
|
# The module list is kept identical to lib/host/conformance.sh so what serves is
|
|
# exactly what the suites verify.
|
|
|
|
set -uo pipefail
|
|
# Project root: SX_PROJECT_DIR in containers (set to /app by the compose stack),
|
|
# else the git toplevel for local runs.
|
|
cd "${SX_PROJECT_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || echo .)}"
|
|
|
|
SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}"
|
|
if [ ! -x "$SX_SERVER" ]; then
|
|
SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe"
|
|
fi
|
|
if [ ! -x "$SX_SERVER" ]; then
|
|
echo "ERROR: sx_server.exe not found." >&2
|
|
exit 1
|
|
fi
|
|
|
|
PORT="${HOST_PORT:-8910}"
|
|
|
|
# Modules: every load line from conformance.sh's MODULES list, minus the ledger
|
|
# (not needed to serve). server.sx supplies host/serve.
|
|
MODULES=(
|
|
"spec/stdlib.sx"
|
|
"lib/r7rs.sx"
|
|
"lib/apl/runtime.sx"
|
|
"lib/datalog/tokenizer.sx"
|
|
"lib/datalog/parser.sx"
|
|
"lib/datalog/unify.sx"
|
|
"lib/datalog/db.sx"
|
|
"lib/datalog/builtins.sx"
|
|
"lib/datalog/aggregates.sx"
|
|
"lib/datalog/strata.sx"
|
|
"lib/datalog/eval.sx"
|
|
"lib/datalog/api.sx"
|
|
"lib/datalog/magic.sx"
|
|
"lib/acl/schema.sx"
|
|
"lib/acl/facts.sx"
|
|
"lib/acl/engine.sx"
|
|
"lib/acl/explain.sx"
|
|
"lib/acl/audit.sx"
|
|
"lib/acl/federation.sx"
|
|
"lib/acl/api.sx"
|
|
"lib/relations/schema.sx"
|
|
"lib/relations/engine.sx"
|
|
"lib/relations/api.sx"
|
|
"lib/relations/explain.sx"
|
|
"lib/relations/federation.sx"
|
|
"lib/relations/tree.sx"
|
|
"lib/feed/normalize.sx"
|
|
"lib/feed/stream.sx"
|
|
"lib/feed/api.sx"
|
|
"lib/smalltalk/tokenizer.sx"
|
|
"lib/smalltalk/parser.sx"
|
|
"lib/guest/reflective/class-chain.sx"
|
|
"lib/smalltalk/runtime.sx"
|
|
"lib/guest/reflective/env.sx"
|
|
"lib/smalltalk/eval.sx"
|
|
"lib/persist/event.sx"
|
|
"lib/persist/backend.sx"
|
|
"lib/persist/log.sx"
|
|
"lib/persist/kv.sx"
|
|
"lib/persist/api.sx"
|
|
"lib/content/block.sx"
|
|
"lib/content/doc.sx"
|
|
"lib/content/render.sx"
|
|
"lib/content/api.sx"
|
|
"lib/content/store.sx"
|
|
"lib/persist/durable.sx"
|
|
"lib/dream/types.sx"
|
|
"lib/dream/json.sx"
|
|
"lib/dream/auth.sx"
|
|
"lib/dream/error.sx"
|
|
"lib/dream/router.sx"
|
|
"lib/host/handler.sx"
|
|
"lib/host/middleware.sx"
|
|
"lib/host/sxtp.sx"
|
|
"lib/host/router.sx"
|
|
"lib/host/feed.sx"
|
|
"lib/host/relations.sx"
|
|
"lib/host/blog.sx"
|
|
"lib/host/server.sx"
|
|
)
|
|
|
|
EPOCH=1
|
|
{
|
|
for M in "${MODULES[@]}"; do
|
|
echo "(epoch $EPOCH)"; echo "(load \"$M\")"; EPOCH=$((EPOCH+1))
|
|
done
|
|
# Point the blog at the DURABLE file backend (persists under $SX_PERSIST_DIR),
|
|
# then idempotently seed a welcome post — re-seeding is a no-op if it already
|
|
# exists on disk, so restarts don't duplicate blocks.
|
|
echo "(epoch $EPOCH)"
|
|
echo "(eval \"(host/blog-use-store! (persist/durable-backend))\")"
|
|
EPOCH=$((EPOCH+1))
|
|
echo "(epoch $EPOCH)"
|
|
# Materialise any persisted posts into the in-memory view, then ensure the
|
|
# welcome post exists (idempotent). Both run on the main thread (IO is fine
|
|
# here; request handlers only read the view).
|
|
echo "(eval \"(host/blog-load-all!)\")"
|
|
EPOCH=$((EPOCH+1))
|
|
echo "(epoch $EPOCH)"
|
|
echo "(eval \"(host/blog-seed! \\\"welcome\\\" \\\"Welcome to the SX host\\\" \\\"This page is rendered by lib/host on the SX runtime, persisted in the SX store — no Quart.\\\" 1)\")"
|
|
EPOCH=$((EPOCH+1))
|
|
echo "(epoch $EPOCH)"
|
|
# Anonymous read endpoints: feed timeline + relations container reads + blog
|
|
# post detail (blog-routes LAST — the :slug catch-all must not shadow the rest).
|
|
# Guarded write groups (auth/ACL or internal-HMAC) are added here once their
|
|
# injected policy is supplied at wiring time.
|
|
echo "(eval \"(host/serve $PORT (list host/feed-routes host/relations-routes host/blog-routes))\")"
|
|
} | exec "$SX_SERVER"
|