Live collections

Every tab keeps its own filter. PubSub sends a tiny nudge, then each browser reloads the collection with the signals it actually holds.

Demo

Changes arrive through the open PubSub stream.

This tab's filtered query

Switch another tab to a different status, then mutate either one.

reloading

Bjfh

active

work item 5

Segsg

active

work item 4

Ship collection nudge

done

work item 3

Verify signal contract

active

work item 2

Review edge deployment

active

work item 1

How it works

  • The stream knows that data changed, but never guesses what a tab is showing.
  • nudge/2 changes nudges.work_items; on_nudge/2 posts the tab's current signals.
  • reload queries Postgres with that tab's statusFilter and patches one panel.
  • Only the separate unfiltered arrival feed uses append_elements/3.

The filtered collection deliberately does not receive row mutations. An item can leave one filter and enter another, so every open tab re-runs its own query. The arrival lane is the contrast: it contains immutable creation facts in append order, making a direct append correct rather than merely faster.

lib/dstar_demo_web/pages/live_collections_page.ex
def handle_connect(conn, _params) do
  :ok = LiveCollections.subscribe()
  nudge(conn, "work_items")
end

# ...

def handle_info({:live_collection_changed, :created, item}, conn) do
  conn
  |> nudge("work_items")
  |> append_elements(arrival_row(%{item: item}), "#arrival-feed")
end

def handle_info({:live_collection_changed, :updated, _item}, conn) do
  nudge(conn, "work_items")
end