DreamLake

14 · Dashboard observability

The reactive surface. An invocation submitted from the CLI or SDK should appear in the dashboard's Invocations view, transition through states, and report its outcome — with no page refresh.

Exercises

  • The dashboard's long-poll loop against GET /v1/admin/invocations.
  • Cursor-based change detection: the response carries a cursor and the next request holds until the server's cursor moves past it.
  • CORS for cross-origin browser fetches (Netlify origin → Heroku control plane).

Requires

  • The control plane up, and the dashboard either running locally or the hosted one at demo.lakeshore.dreamlake.ai.
  • At least one daemon registered and draining the queue you submit to, or the row will sit in queued forever.
  • Admin auth — /v1/admin/* is gated on LAKESHORE_ADMIN_TOKEN, or passes freely in dev open mode when that variable is unset.
The admin invocations feed is default-namespace only

GET /v1/admin/invocations resolves the default namespace and reads its invocations. There is no namespace query parameter. Submitting into some other namespace produces a row the dashboard's Invocations view will not show.

Verifies

Submit → live state transitions visible in the browser without a manual refresh.

Run

In one terminal, submit:

bash
export LAKESHORE_WORKSPACE=~/lakeshore-workspace
export LAKESHORE_URL=http://localhost:8080

uv run --project $LAKESHORE_WORKSPACE/lakeshore-py \
  $LAKESHORE_WORKSPACE/lakeshore-examples/09-hello-queue-udf/hello_udf.py

In the browser, open the dashboard and go to Invocations.

Expected output

A new row appears, moves queued → running → succeeded, and settles with a result preview. The delay before it appears is bounded by the long-poll window, not by a fixed refresh interval.

The long-poll contract

Query paramDefaultCap
cursor0—
timeout_s3060
limit100500

The request blocks until the server's adminCursor passes the supplied cursor, or the timeout expires. The response is { invocations, cursor }; feed that cursor back into the next request. Rows are ordered newest-submitted first, and each carries id, queueName, functionQualname, state, workerId, the three timestamps, and progress.

queueName is read off runConfig.queue — Phase A.5 removed Invocation.queueId, so there is no join and no foreign key. Rows with nothing there render as default.

If it fails

SymptomLikely cause
The row never appearsSubmitted into a non-default namespace — see the callout above — or into a namespace the dashboard account is not pointed at.
The row appears but stays queuedNothing is draining the queue. Check lakeshore daemon list and the daemon's queues column.
401 on /v1/admin/invocationsThe control plane has LAKESHORE_ADMIN_TOKEN set and the dashboard is not sending it.
CORS error in the browser consoleThe control plane registers @fastify/cors with origin: true (reflect any origin), so a CORS failure usually means the request never reached it — check the URL and TLS first.
The row appears but never updatesThe long-poll hung. Look for the /v1/admin/invocations?cursor=… request in the Network panel; a request that returns without the cursor advancing is the tell.

Status

Manual.

Next

→ 15 · Token lifecycle