PhoenixKitKnowledgeBase.Collab (PhoenixKitKnowledgeBase v0.1.0)

Copy Markdown View Source

One Leaf.Collab.Room per note, started when somebody opens it.

Leaf holds a shared document in a process and has no opinion about how those processes are named or supervised — that is the host's job, and this is it.

Why a room is temporary

A room that crashes is not restarted with what it was holding, because it is not holding anything any more: the document lived in its state. The next person to open the note starts a fresh room, which loads from PhoenixKitKnowledgeBase.Collab.Store — that is, from the file, which is the source of truth anyway. Restarting would only produce an empty room wearing the name of a note.

Stopping rooms

Under Leaf 0.6 a room outlived its sessions: its {:DOWN, …} clause dropped the departed session and returned {:noreply, …}, with no stop and no idle timeout, so a room started for a note stayed up for the life of the node. close_room/1 exists for that — GenServer.stop/1 rather than a kill, because the last thing a room does is write down what it was holding.

Leaf ≥ 0.8, which is what core admits today, takes :idle_after and stops an empty room itself. Nothing opens a room yet (this is groundwork; no LiveView calls room_for/1), so room_spec/1 does not pass it: when rooms are wired to the editor, pass idle_after: there and close_room/1 becomes the backstop rather than the only way down.

Why this is in children/0

PhoenixKit.Module collects child specs from every discovered module and starts them under core's supervisor, so this needs no host setup. They start whether or not the knowledge base is enabled — a registry and an idle dynamic supervisor, which cost nothing until a note is opened.

Summary

Functions

Child specs for core's supervisor. See PhoenixKitKnowledgeBase.children/0.

Stop the room for this note, flushing what it holds on the way down.

The room holding this note, started if nobody has opened it yet.

Whether a room is currently open for this note, without starting one.

Functions

children()

@spec children() :: [Supervisor.child_spec() | {module(), term()}]

Child specs for core's supervisor. See PhoenixKitKnowledgeBase.children/0.

close_room(note_uuid)

@spec close_room(String.t()) :: :ok

Stop the room for this note, flushing what it holds on the way down.

Rooms do not stop themselves — see the moduledoc — so whatever opened one is responsible for this. A note nobody has open should not still have a process.

room_for(note)

@spec room_for(PhoenixKitKnowledgeBase.Schemas.Note.t()) ::
  {:ok, pid()} | {:error, term()}

The room holding this note, started if nobody has opened it yet.

Safe to call from several sessions at once: the loser of the race gets {:already_started, pid} back from the registry and uses that room, which is the whole point of naming them.

room_open?(note_uuid)

@spec room_open?(String.t()) :: boolean()

Whether a room is currently open for this note, without starting one.