Sofa.Changes.Parser (sofa v0.5.1)

Copy Markdown View Source

Decodes _changes responses into events, using pure functions.

A continuous feed is one JSON object per line, arriving in chunks that may split a line or have several. Empty lines are heartbeats. The normal and longpoll feeds are a single JSON body with results and last_seq. Both end up as the same formatted stream of events:

  • {:change, row} for a document change, a map with "id", "seq", "changes" and optionally "deleted" and "doc"
  • {:last_seq, seq} for the bare {"last_seq": ...} object a feed ends with, or the last_seq of a batch
  • {:error, map} for {"error": ..., "reason": ...} objects, which CouchDB can emit inside a stream, and for lines that are not JSON

Sequences are opaque and are passed through untouched.

Examples

iex> {events, rest} = Sofa.Changes.Parser.feed("", ~s({"seq": 1, "id": "a", "changes": []}\n\n{"last_))
iex> events
[{:change, %{"seq" => 1, "id" => "a", "changes" => []}}]
iex> rest
~s({"last_)
iex> Sofa.Changes.Parser.feed(rest, ~s(seq": 1}\n))
{[{:last_seq, 1}], ""}

Summary

Functions

The events for a normal or longpoll body. The rows come first, in order, followed by the batch's last_seq.

Appends chunk to the buffered partial line, returns the events for every complete line, and the remaining partial line as the new buffer.

Decodes whatever is left in the buffer once the response has ended. A well-behaved server ends with a newline, leaving nothing. Anything else is decoded as a final line.

Types

event()

@type event() :: {:change, row()} | {:last_seq, term()} | {:error, map()}

row()

@type row() :: %{required(String.t()) => term()}

Functions

batch(error)

@spec batch(map()) :: [event()]

The events for a normal or longpoll body. The rows come first, in order, followed by the batch's last_seq.

feed(buffer, chunk)

@spec feed(binary(), binary()) :: {[event()], binary()}

Appends chunk to the buffered partial line, returns the events for every complete line, and the remaining partial line as the new buffer.

flush(buffer)

@spec flush(binary()) :: [event()]

Decodes whatever is left in the buffer once the response has ended. A well-behaved server ends with a newline, leaving nothing. Anything else is decoded as a final line.