ExternalSource
SPI for streaming transactions into a database from an upstream feed (a CDC source, message log, etc.) instead of XTDB's own DML.
The source owns the read side of its upstream: it receives events (via polling or other methods), maps each to a transaction, and submits it through TxIndexer.executeTx.
XTDB drives the source via onPartitionAssigned and persists the per-tx ExternalSourceToken so the source can resume after the last indexed event.
One instance per database on each node that could lead it, opened and closed with the database there. A node that indexes nothing, or holds the database read-only, can never lead and so opens no source at all.
That instance spans every leader term the node serves, so onPartitionAssigned may be called repeatedly (sequentially, never concurrently). State belonging to one term therefore MUST live inside that call, not in a field: the upstream connection is torn down on cancellation and there is no close in between to reset anything.
A source that also confirms progress upstream — advancing a Postgres replication slot, committing a consumer-group offset — must gate that on TxIndexer.latestBlock rather than on a transaction's own durability handle. Confirmation tells the upstream it may discard everything behind the confirmed position, so confirming a transaction that is only on the replica log leaves XTDB the sole holder of data nobody can re-send. Resuming is different: resume from the furthest position indexed, which may legitimately be ahead of the last block.
Types
Opens an ExternalSource for a database, from the source config. Called once per database open, and a throw here fails that open — so validation that needs nothing from the upstream belongs here, where a misconfiguration surfaces on the node whose config carries it.
Makes a Factory persistable. A factory whose class is claimed by a ServiceLoader-discovered registration serialises (via protoTag / toProto) and so can travel as a stored secondary-database config; a programmatic factory with no registration still runs in-process, but Factory.toProto rejects it.
Functions
Called when a leader term for partition begins on this node, to run the source's poll loop.