Ankusa.Sink.GooglePubSub.Batcher (ankusa v0.7.0)

Copy Markdown View Source

Ankusa.Sink.GooglePubSub's codec for Ankusa.Sink.Batcher: up to 1 000 deliveries to one topic become one topics.publish request.

publish is all or nothing: a 200 names one message id per message, and a refusal answers the request as a whole with no per-message result. So the reply maps back like this:

  • a 200 with one id for each message: every entry is :ok; any other 200 fails every entry with {:unexpected_reply, body}.
  • a transient error (UNAVAILABLE, a 5xx, a timeout, no credentials), a config error (NOT_FOUND, PERMISSION_DENIED, UNAUTHENTICATED: every message's fault, so a permanent {:config, _} for each) or a throttle (RESOURCE_EXHAUSTED, 429, 503): every entry gets it, with its own retry class and jitter, and retries on its own.
  • INVALID_ARGUMENT for one message: the request is bisected. Its two halves are published one after the other (so the entries' order is kept), and a half that is refused again is split again, until the refused message stands alone and is {:permanent, {:pubsub, status, "INVALID_ARGUMENT", message}} while every other message of the batch is delivered. One bad message among 999 good ones takes 2 * log2(1000) extra requests, and the work is bounded: a batch of n spends at most 2 * (ceil(log2 n) + 1) splits, after which the entries still unresolved are {:batch_rejected, reason} (transient: they retry, in other batches). The extra requests are counted in ankusa_sink_batch_bisections_total.

Ankusa.Sink.GooglePubSub checks a message's size and attributes before it enters a batch, so the usual causes of a refusal never reach one.