VerifiedPubSub.Api (VerifiedPubSub v0.1.0)

Copy Markdown View Source

The call-site API: subscribe/2, unsubscribe/2, topic/2, broadcast/4, broadcast!/4, broadcast_from/5 and broadcast_from!/5.

use VerifiedPubSub, manifest: MyApp.Topics imports these macros, and so does use VerifiedPubSub.Subscriber:

broadcast!(:pets, %{owner_id: id}, :adopted, payload)

Argument order

In every macro here, the params come immediately after the topic. The params only fill in the segments of the topic, so {topic, params} is the address and {event, payload} is the message. Phoenix.PubSub.broadcast/3 has the same order: the address, then the message. Also, the two atoms are never next to each other, so a call site cannot swap them without notice.

Why macros rather than functions

These are macros, so the topic and the event must be literal atoms. Because of this, an unknown topic or event is a CompileError that names the valid choices. A call site can build the params at runtime. The macro checks a literal params map at compile time. A params map built at runtime raises KeyError from Map.fetch!/2 when a key is missing.

A plain function that takes atoms gets no check at compile time. Elixir's type inference does not narrow across clause heads on a remote call. So a broadcast/4 defined as

def broadcast(:pets, %{owner_id: id}, :adopted, payload), do: ...

gives no diagnostic at all for broadcast(:pets, params, :adoptd, ...). We checked this on Elixir 1.20.4. The call fails at runtime instead. A macro can find the topic and the event in the manifest while your code compiles.

The macros have these costs:

  • each module that calls them needs the import
  • a pipe cannot pass a value into them
  • & cannot capture them
  • apply/3 cannot call them

Broadcasts that skip the sender

broadcast_from/5 and broadcast_from!/5 work like Phoenix.PubSub.broadcast_from/4. from comes first for the same reason that it does there:

broadcast_from!(self(), :pets, %{owner_id: id}, :adopted, payload)

A common use is a LiveView that writes to a topic and also subscribes to it. Without these macros, the LiveView applies its own change twice.

from is the pid that you pass, so self() is the process that makes the call. When a context function, a Task, or an Oban job makes the broadcast, self() is that process, not the process that started the request. In that case, pass the pid of the process that started the request.

Summary

Functions

Broadcasts an event on a topic that takes no params.

Broadcasts an event on a topic.

Broadcasts an event on a topic that takes no params, and raises on failure.

Broadcasts an event on a topic, and raises on failure.

Broadcasts on a topic that takes no params, to every subscribed process except from.

Broadcasts to every subscribed process except from.

Broadcasts on a topic that takes no params, to every subscribed process except from, and raises on failure.

Broadcasts to every subscribed process except from, and raises on failure.

Subscribes the current process to a topic.

Unsubscribes the current process from a topic.

Functions

broadcast(topic, event, payload)

(macro)

Broadcasts an event on a topic that takes no params.

It is the same as broadcast(topic, %{}, event, payload). When the topic takes params, the call is a compile error. subscribe/1 works the same way.

broadcast(topic, params, event, payload)

(macro)

Broadcasts an event on a topic.

broadcast!(topic, event, payload)

(macro)

Broadcasts an event on a topic that takes no params, and raises on failure.

broadcast!(topic, params, event, payload)

(macro)

Broadcasts an event on a topic, and raises on failure.

broadcast_from(from, topic, event, payload)

(macro)

Broadcasts on a topic that takes no params, to every subscribed process except from.

broadcast_from(from, topic, params, event, payload)

(macro)

Broadcasts to every subscribed process except from.

broadcast_from!(from, topic, event, payload)

(macro)

Broadcasts on a topic that takes no params, to every subscribed process except from, and raises on failure.

broadcast_from!(from, topic, params, event, payload)

(macro)

Broadcasts to every subscribed process except from, and raises on failure.

subscribe(topic, params \\ quote do %{} end)

(macro)

Subscribes the current process to a topic.

topic(topic, params \\ quote do %{} end)

(macro)

Returns the wire topic.

unsubscribe(topic, params \\ quote do %{} end)

(macro)

Unsubscribes the current process from a topic.