Sofa.Changes.Query (sofa v0.5.1)

Copy Markdown View Source

Turns follower options into the request for GET|POST /{db}/_changes.

The CouchDB changes API takes its parameters in the query string, with two exceptions that need a POST and a JSON body: the _doc_ids and _selector filters. This module encodes the documented parameters the way CouchDB expects them, see https://docs.couchdb.org/en/stable/api/database/changes.html

Options

Every option is sent as the query parameter of the same name, encoded as:

  • booleans, integers and atoms become their string form (true, 5, all_docs, now)
  • strings are sent verbatim, so style: "all_docs" works as well
  • nil drops the parameter, so heartbeat: nil lets the server side timeout end the response. Dropping both is refused, as nothing would ever end a quiet feed and a dead connection would go unnoticed

A few options are special:

  • :feed defaults to :continuous. :longpoll and :normal are the alternatives
  • longpoll: true is shorthand for feed: :longpoll
  • :heartbeat defaults to 60 000 ms and :timeout to 7 200 000 ms
  • :since is kept on the struct so the follower can advance it between reconnects. It is sent verbatim and never parsed. Only :now or an opaque sequence string are accepted. Anything else raises an ArgumentError. Omitting it leaves since as nil and drops the parameter, which begins at the start of the feed
  • doc_ids: [...] switches to POST with filter=_doc_ids and the ids in the body, overriding any :filter
  • selector: %{...} does the same with filter=_selector
  • query_params: [k: v] adds raw parameters, as used for filter function arguments

Examples

iex> Sofa.Changes.Query.new([]) |> Sofa.Changes.Query.params()
[{"feed", "continuous"}, {"heartbeat", "60000"}, {"timeout", "7200000"}]

iex> Sofa.Changes.Query.new(longpoll: true, since: "42", heartbeat: nil)
...> |> Sofa.Changes.Query.params()
[{"feed", "longpoll"}, {"timeout", "7200000"}, {"since", "42"}]

iex> %Sofa.Changes.Query{method: :post, body: body} =
...>   Sofa.Changes.Query.new(doc_ids: ["a", "b"], filter: "ignored")
iex> body
%{"doc_ids" => ["a", "b"]}

Summary

Functions

Whether rows will carry the document under "doc".

Builds a query from follower options, see the module documentation.

The query string parameters for the next request, with since included when known. The order is stable: feed, then the remaining options in the order given, then since.

Advances since, as after a delivered row or a last_seq.

Types

feed()

@type feed() :: :continuous | :longpoll | :normal

since()

@type since() :: String.t() | :now | nil

t()

@type t() :: %Sofa.Changes.Query{
  body: map() | nil,
  feed: feed(),
  heartbeat: pos_integer() | nil,
  method: :get | :post,
  params: [{String.t(), String.t()}],
  since: since(),
  timeout: pos_integer() | nil
}

Functions

include_docs?(query)

@spec include_docs?(t()) :: boolean()

Whether rows will carry the document under "doc".

Examples

iex> Sofa.Changes.Query.new(include_docs: true) |> Sofa.Changes.Query.include_docs?()
true
iex> Sofa.Changes.Query.new([]) |> Sofa.Changes.Query.include_docs?()
false

new(opts)

@spec new(keyword()) :: t()

Builds a query from follower options, see the module documentation.

Raises ArgumentError on an unknown :feed, or when both :heartbeat and :timeout are nil.

params(query)

@spec params(t()) :: [{String.t(), String.t()}]

The query string parameters for the next request, with since included when known. The order is stable: feed, then the remaining options in the order given, then since.

since(query, since)

@spec since(t(), since()) :: t()

Advances since, as after a delivered row or a last_seq.