Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Live Updates

Crap CMS supports real-time event streaming for mutation notifications. When documents are created, updated, or deleted, events are broadcast to connected subscribers.

Technology

  • gRPC Server Streaming (Subscribe RPC) for API consumers
  • SSE (GET /admin/events) for the admin UI
  • Internal bus: tokio::sync::broadcast channel

Configuration

In crap.toml:

[live]
enabled = true           # default: true
channel_capacity = 1024  # default: 1024
# max_sse_connections = 1000        # max concurrent SSE connections (0 = unlimited)
# max_subscribe_connections = 1000  # max concurrent gRPC Subscribe streams (0 = unlimited)

Set enabled = false to disable live updates entirely. Both SSE and gRPC Subscribe will be unavailable.

Connection limits protect against resource exhaustion. When the limit is reached, new SSE connections receive 503 Service Unavailable and new gRPC Subscribe calls receive UNAVAILABLE status. Existing connections are not affected.

Per-Collection Control

Each collection (and global) can control whether it emits events via the live field:

-- Broadcast all events (default when absent)
crap.collections.define("posts", { ... })

-- Disable broadcasting entirely
crap.collections.define("audit_log", {
    live = false,
    ...
})

-- Dynamic: Lua function decides per-event
crap.collections.define("posts", {
    live = "hooks.posts.should_broadcast",
    ...
})

The function receives { collection, operation, data } and returns true to broadcast or false/nil to suppress.

Event Structure

Each event contains:

FieldDescription
sequenceMonotonic sequence number
timestampISO 8601 timestamp
target"collection" or "global"
operation"create", "update", or "delete"
collectionCollection or global slug
document_idDocument ID
dataFull document fields (empty for delete)

Event Pipeline

Transaction:
  before-hooks → DB operation → after-hooks → commit

After commit:
  -> publish_event()
       1. live setting check
       2. before_broadcast hooks
       3. EventBus.publish()
            -> gRPC Subscribe stream
            -> Admin SSE stream

Limitations (V1)

  • Events are ephemeral — missed events are not replayed
  • Access is snapshotted at subscribe time — permission changes require reconnect
  • No field-level subscription filters
  • No event persistence or replay
  • before_broadcast hooks have no CRUD access (fires after commit)