Ankusa.Intake.Reconciler (ankusa v0.7.0)

Copy Markdown View Source

Carries half-persisted hooks to completion (ADR 0002, sections 3 and 5). Under wal: :dual a record the writer issued to both places may end with only one of them: the local store (the log refused or timed out) or the log (the store write failed). The provider got a 503, and the half that persisted still exists, so the record is completed, never undone:

  • log half missing: publish it again (up to 256 records at a time)
  • local half missing: Queue.Writer re-applies the batch's ops, after one point read says the first write did not land after all
  • both missing: local first (the cheaper half, and it makes the hook deliverable), then the log

Retries back off per record from 100 ms to 5 s, jittered; a throttled class honours its retry_after; a permanent class (the record can never fit, the topic is gone) never completes and is stuck straight away. Nothing is ever dropped. A record not completed within intake.reconcile_deadline_ms is stuck: its fleet dedupe claim is released (a retry is then admitted as a new hook with the same idempotency_key, never an acked loss) and the reconciler keeps trying.

The claim of a carried hook is neither promoted nor released until both halves are confirmed (hold/3); the reconciler promotes it then.

This is the live component. Boot-time recovery is Ankusa.Intake.Recovery.

Summary

Functions

Returns a specification to start this module under a supervisor.

Settles the claims of entries a pass or the writer completed.

Hand the reconciler the dedupe claim of carried hook id. :held: it will promote it when both halves are confirmed. :completed: it already finished, promote it yourself. :stuck: release it yourself. ETS only; no call.

Run a pass now (the writer calls it after it carried a batch).

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

finish(instance, entries, half)

@spec finish(atom(), [tuple()], :local | :log) :: :ok

Settles the claims of entries a pass or the writer completed.

hold(instance, id, claim)

@spec hold(atom(), String.t(), term()) :: :held | :completed | :stuck

Hand the reconciler the dedupe claim of carried hook id. :held: it will promote it when both halves are confirmed. :completed: it already finished, promote it yourself. :stuck: release it yourself. ETS only; no call.

start_link(opts)

wake(instance)

@spec wake(atom()) :: :ok

Run a pass now (the writer calls it after it carried a batch).