Skip to content

refactor(core)!: panic-free builder validation — build() collects all configuration errors (034 Phase 2, #133)#138

Merged
lxsaah merged 1 commit into
mainfrom
refactor/034-phase2-133-build-validation
Jun 10, 2026
Merged

refactor(core)!: panic-free builder validation — build() collects all configuration errors (034 Phase 2, #133)#138
lxsaah merged 1 commit into
mainfrom
refactor/034-phase2-133-build-validation

Conversation

@lxsaah

@lxsaah lxsaah commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes #133. Part of design 034 Phase 2 (review doc §3.4); second of three stacked PRs (#130#133#134). Builds on #137.

What

One failure model instead of two: builder methods never panic on user mistakes; build() validates everything and returns all errors at once.

  • New public ConfigError { record_key, url, message } + DbError::InvalidConfiguration { errors: Vec<ConfigError> } (code 0x4003, included in is_configuration_error).
  • TypedRecord::set_producer / set_transform / add_inbound_connector: mutual-exclusion violations and duplicate producer/transform are recorded and the conflicting registration is skipped (has_producer() stays false after a conflicting .source()).
  • OutboundConnectorBuilder::finish() / InboundConnectorBuilder::finish(): invalid URL, missing serializer/deserializer, unregistered scheme, transform/source conflicts → recorded with record key + URL; the link is not registered; the registrar is returned as usual so chains keep compiling.
  • Spawn-time factory panics become build()-time checks: a record with an outbound/inbound link and no buffer now fails build() with key + link URL (previously: panic inside a factory closure during the connector phase, far from the user's mistake). Consequence: .buffer() after .link_to()/.link_from() is now legal — order-independent (covered by a new test).
  • configure() re-registering a key with a different type: recorded, user closure skipped (was assert!).
  • Duplicate keys and DependencyGraph findings (cycles, unregistered transform inputs) fold into the same collected report. Note for reviewers: callers matching DuplicateRecordKey/CyclicDependency from build() must switch to InvalidConfiguration — flagged per the issue's directive to collect all errors.
  • Remaining panic!/expects on the builder path are internal invariants only, worded "this is a bug in aimdb-core".
  • AnyRecord gains has_buffer() and drain_config_errors() (breaking for external implementors).

Acceptance criteria (from #133)

  • Grep of panic!/assert! in typed_api.rs/typed_record.rs/builder.rs shows only internal-invariant messages
  • A builder with three distinct mistakes reports all three from one build() call (build_reports_all_configuration_mistakes_at_once)
  • Every error carries the record key and (where applicable) the connector URL
  • Error construction is single-shape per refactor(core): unify DbError on alloc::String — remove std/no_std dual-field variants #129
  • make check passes; examples unchanged

Tests

The 6 #[should_panic] tests are converted to recorded-error assertions; new tests cover unregistered-scheme recording, the three-mistakes acceptance criterion, buffer-after-link order independence, linked-record-without-buffer at build(), and InvalidConfiguration's Display/error-code. The tokio adapter's test_duplicate_key_error now asserts the collected error instead of a configure-time panic.

🤖 Generated with Claude Code

… configuration errors (#133)

One failure model instead of two: builder methods never panic on user
mistakes. TypedRecord setters, the connector-link finish() methods, and
configure() record a ConfigError (skipping the conflicting
registration) and build() returns a single
DbError::InvalidConfiguration carrying every finding — record key and
connector URL included — so one run surfaces every mistake.

The spawn-time factory panics (missing buffer, record lookup) become
build()-time checks; .buffer() after .link_to()/.link_from() is now
legal. Duplicate keys and dependency-graph findings fold into the same
collected report. Remaining panics on the builder path are internal
invariants worded 'this is a bug in aimdb-core'.

AnyRecord gains has_buffer() and drain_config_errors().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lxsaah lxsaah merged commit 576efb5 into main Jun 10, 2026
5 checks passed
@lxsaah lxsaah deleted the refactor/034-phase2-133-build-validation branch June 10, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(core): replace panic-based builder validation with collected configuration errors from build()

1 participant