View Source EchoPubSub.Producer.State (EchoPubSub v0.2.0)

The producer's state and the only place that changes it. Other modules read fields directly but update them through the named functions here.

Summary

Types

t()

Fields

Functions

Records that node acked every message below target.

Acks every write for this node: Phoenix delivered them to local subscribers already.

Whether node has not acked every write yet.

Whether node is further behind than the buffer can replay.

Clears the flush timer once the flush runs.

The registration or delivery a task ref belongs to. Every ref is in exactly one map: registrations and deliveries never share a ref.

Drops every trace of nodes, so they register from scratch if they return.

A fresh state for group: empty buffer, no known nodes.

What registered node still needs from the buffer.

Marks node registered with pid, keeping its cursor if it had one.

Keeps a failed registration's start cursor for the retry; no task runs meanwhile.

Whether a registration task for node is running (not a failed one waiting to retry).

The start cursor a failed registration of node retries from, or nil.

Records the pending flush timer.

Records when the last capacity warning fired.

Records a batch in flight to node, acking up to target once it succeeds.

Records a running registration task for node.

Writes the slowest node has not acked yet.

Forgets the batch in flight to node.

Stores message at the write cursor and moves the cursor on.

Types

@type cursor() :: non_neg_integer()
@type t() :: %EchoPubSub.Producer.State{
  batch_interval: timeout(),
  buffer: EchoPubSub.Producer.RingBuffer.t(),
  call_timeout: timeout(),
  capacity_warning_interval: non_neg_integer(),
  capacity_warning_threshold: number(),
  flush_timer: (reference() | nil) | nil,
  group: atom(),
  in_flight: %{required(node()) => {reference(), cursor()}},
  last_capacity_warning_at: (integer() | nil) | nil,
  read_cursors: %{required(node()) => cursor()},
  registering: %{required(node()) => {reference() | nil, cursor(), pid()}},
  workers: %{required(node()) => pid()},
  write_cursor: cursor()
}

Fields:

  • group - the :pg group this producer delivers to (its delivery scope)
  • write_cursor - count of messages ever written; the next write lands here
  • read_cursors - map of node to its next-needed cursor; everything below it that node has acked. A node is absent until its registration is acked
  • registering - map of node to the {task reference, start cursor, worker pid} of its pending registration; the reference is nil while a failed attempt waits for its retry
  • workers - map of node to the worker pid this producer last registered with
  • in_flight - map of node to the {task reference, target cursor} of the batch being delivered to it
  • buffer - ring buffer of the last buffer_size messages; oldest overwritten on wrap
  • batch_interval - milliseconds to batch writes before a flush; 0 flushes immediately
  • call_timeout - timeout in milliseconds for synchronous calls to remote nodes
  • capacity_warning_threshold - buffer fill ratio that triggers a capacity warning
  • capacity_warning_interval - minimum seconds between capacity warnings
  • flush_timer - reference of the pending flush timer, or nil when none is scheduled
  • last_capacity_warning_at - monotonic seconds of the last capacity warning, or nil if never

Functions

Link to this function

ack(state, node, target)

View Source
@spec ack(t(), node(), cursor()) :: t()

Records that node acked every message below target.

@spec ack_local(t()) :: t()

Acks every write for this node: Phoenix delivered them to local subscribers already.

@spec behind?(t(), node()) :: boolean()

Whether node has not acked every write yet.

Link to this function

beyond_buffer?(state, node)

View Source
@spec beyond_buffer?(t(), node()) :: boolean()

Whether node is further behind than the buffer can replay.

Link to this function

clear_flush_timer(state)

View Source
@spec clear_flush_timer(t()) :: t()

Clears the flush timer once the flush runs.

@spec find_task(t(), reference()) ::
  {:registration, node(), cursor(), pid()}
  | {:delivery, node(), cursor()}
  | :unknown

The registration or delivery a task ref belongs to. Every ref is in exactly one map: registrations and deliveries never share a ref.

@spec forget(t(), [node()]) :: t()

Drops every trace of nodes, so they register from scratch if they return.

@spec new(atom(), [EchoPubSub.Producer.option()]) :: t()

A fresh state for group: empty buffer, no known nodes.

@spec pending(t(), node()) :: EchoPubSub.Producer.RingBuffer.pending()

What registered node still needs from the buffer.

Link to this function

registered(state, node, pid, start)

View Source
@spec registered(t(), node(), pid(), cursor()) :: t()

Marks node registered with pid, keeping its cursor if it had one.

Link to this function

registration_failed(state, node, start, pid)

View Source
@spec registration_failed(t(), node(), cursor(), pid()) :: t()

Keeps a failed registration's start cursor for the retry; no task runs meanwhile.

Link to this function

registration_running?(state, node)

View Source
@spec registration_running?(t(), node()) :: boolean()

Whether a registration task for node is running (not a failed one waiting to retry).

Link to this function

retry_start(state, node)

View Source
@spec retry_start(t(), node()) :: cursor() | nil

The start cursor a failed registration of node retries from, or nil.

Link to this function

set_flush_timer(state, ref)

View Source
@spec set_flush_timer(t(), reference()) :: t()

Records the pending flush timer.

Link to this function

set_last_warning(state, at)

View Source
@spec set_last_warning(t(), integer() | nil) :: t()

Records when the last capacity warning fired.

Link to this function

track_delivery(state, node, ref, target)

View Source
@spec track_delivery(t(), node(), reference(), cursor()) :: t()

Records a batch in flight to node, acking up to target once it succeeds.

Link to this function

track_registration(state, node, ref, start, pid)

View Source
@spec track_registration(t(), node(), reference(), cursor(), pid()) :: t()

Records a running registration task for node.

@spec unacked(t()) :: non_neg_integer()

Writes the slowest node has not acked yet.

Link to this function

untrack_delivery(state, node)

View Source
@spec untrack_delivery(t(), node()) :: t()

Forgets the batch in flight to node.

@spec write(t(), term()) :: t()

Stores message at the write cursor and moves the cursor on.