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
200with one id for each message: every entry is:ok; any other200fails every entry with{:unexpected_reply, body}. - a transient error (
UNAVAILABLE, a5xx, 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_ARGUMENTfor 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 takes2 * log2(1000)extra requests, and the work is bounded: a batch ofnspends at most2 * (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 inankusa_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.