Real-time updates for CRM interactions, backed by PhoenixKit.PubSub.Manager.
An interaction appears in the feed of every contact it involves — the subject
contact (interactions.contact_uuid) and any resolved party contacts — so
a change fans out to each of their per-contact topics. A contact's
Interactions tab subscribes to its own topic; any add/edit/delete to an
interaction touching that contact pushes a live refresh.
Messages are {:crm, event, payload} tuples where event is one of
:interaction_created | :interaction_updated | :interaction_deleted and
payload is %{interaction_uuid: uuid}.
Topics are global (no tenant partitioning) — but the per-contact topic is keyed
by uuid, so you can't subscribe without already knowing the contact, which
bounds the fan-out. (Mirrors phoenix_kit_projects — tenant scoping is a
framework-wide gap, not a CRM one.)
Summary
Functions
Fans an interaction change out to every involved contact's feed topic.
Broadcasts an interaction change to an EXPLICIT set of contact feed topics.
Subject contact + any resolved party contacts (deduped, nils dropped). Tolerates parties not being preloaded (treats them as none).
Subscribes the calling process to a topic.
Topic for the interaction feed of a single contact (as subject or party).
Unsubscribes the calling process from a topic.
Functions
@spec broadcast_interaction(atom(), PhoenixKitCRM.Schemas.Interaction.t()) :: :ok
Fans an interaction change out to every involved contact's feed topic.
Best-effort: never raises out to the caller — a saved interaction must not be reported as failed just because the realtime broadcast hiccuped. Call it AFTER the DB commit.
Broadcasts an interaction change to an EXPLICIT set of contact feed topics.
Used by updates, which must reach the union of the old and new involved contacts so a contact dropped by an edit still gets a refresh to remove the entry. Best-effort (rescued).
@spec involved_contact_uuids(PhoenixKitCRM.Schemas.Interaction.t()) :: [binary()]
Subject contact + any resolved party contacts (deduped, nils dropped). Tolerates parties not being preloaded (treats them as none).
Subscribes the calling process to a topic.
Topic for the interaction feed of a single contact (as subject or party).
@spec unsubscribe(String.t()) :: :ok
Unsubscribes the calling process from a topic.