Context
The runtime treats .source(), .transform(), and .link_from() as
interchangeable record producers — all three ultimately call
TypedRecord::produce() and push into the same buffer. There is already
mutual-exclusion at config time between .source() and .transform():
.link_from() is the gap. A node can declare .link_from() alongside
.source() or .transform() on the same key and the runtime will accept
it. Both writers race into Buffer::push and the latest_snapshot becomes
last-writer-wins with no panic, no log, no diagnostic. This is the actual
"two writers per record" misconfiguration — the one worth catching.
Proposal
Extend the existing config-time mutual-exclusion pattern to cover inbound
connectors:
- In
InboundConnectorBuilder::finish
(aimdb-core/src/typed_api.rs:908):
panic if has_transform() or has_producer_service() is already true.
- In
set_producer_service and set_transform: panic if
inbound_connectors() is non-empty.
All three predicates already exist — purely additive, no API change, same
panic-at-config-time semantics as the existing checks.
Scope / decisions
- Multiple
link_from on the same key: keep allowed. add_inbound_connector
pushes onto a Vec, and multiple inbound feeds (redundant brokers, fan-in) is
a legitimate pattern. Only forbid mixing inbound with local producers.
- Where to enforce: existing mutual-exclusion lives on
TypedRecord
(set_producer_service, set_transform). Following that convention argues
for adding the check to add_inbound_connector too, and letting the builder
finish() rely on it. The builder-level check gives a better error message
(includes the URL); the record-level check is harder to bypass. Probably do
both — the record-level as the source of truth, the builder-level as a
pre-check that fires earlier with more context.
- Out of scope: detecting two different nodes both declaring
link_to
on the same key (cross-node writer conflict). That needs network-level
awareness, not local config validation.
Background
Surfaced while reviewing the record-ownership blog draft. The blog originally
framed link_to + link_from on the same key as the misconfiguration to
watch for; the actual writer-conflict case is link_from + a local source.
Context
The runtime treats
.source(),.transform(), and.link_from()asinterchangeable record producers — all three ultimately call
TypedRecord::produce()and push into the same buffer. There is alreadymutual-exclusion at config time between
.source()and.transform():set_producer_servicepanics if a transform is registered(aimdb-core/src/typed_record.rs:638)
set_transformpanics if a source is registered(aimdb-core/src/typed_record.rs:726)
.link_from()is the gap. A node can declare.link_from()alongside.source()or.transform()on the same key and the runtime will acceptit. Both writers race into
Buffer::pushand thelatest_snapshotbecomeslast-writer-wins with no panic, no log, no diagnostic. This is the actual
"two writers per record" misconfiguration — the one worth catching.
Proposal
Extend the existing config-time mutual-exclusion pattern to cover inbound
connectors:
InboundConnectorBuilder::finish(aimdb-core/src/typed_api.rs:908):
panic if
has_transform()orhas_producer_service()is already true.set_producer_serviceandset_transform: panic ifinbound_connectors()is non-empty.All three predicates already exist — purely additive, no API change, same
panic-at-config-time semantics as the existing checks.
Scope / decisions
link_fromon the same key: keep allowed.add_inbound_connectorpushes onto a Vec, and multiple inbound feeds (redundant brokers, fan-in) is
a legitimate pattern. Only forbid mixing inbound with local producers.
TypedRecord(
set_producer_service,set_transform). Following that convention arguesfor adding the check to
add_inbound_connectortoo, and letting the builderfinish()rely on it. The builder-level check gives a better error message(includes the URL); the record-level check is harder to bypass. Probably do
both — the record-level as the source of truth, the builder-level as a
pre-check that fires earlier with more context.
link_toon the same key (cross-node writer conflict). That needs network-level
awareness, not local config validation.
Background
Surfaced while reviewing the record-ownership blog draft. The blog originally
framed
link_to+link_fromon the same key as the misconfiguration towatch for; the actual writer-conflict case is
link_from+ a local source.