Skip to content

feat(iac): ResourceReplacer optional driver hook + DefaultReplace export#577

Merged
intel352 merged 6 commits into
mainfrom
feat/resource-replacer-interface
May 7, 2026
Merged

feat(iac): ResourceReplacer optional driver hook + DefaultReplace export#577
intel352 merged 6 commits into
mainfrom
feat/resource-replacer-interface

Conversation

@intel352

@intel352 intel352 commented May 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • interfaces.ResourceReplacer optional driver interface for resources owning single-attach dependents (e.g., DO Droplets with Block Storage Volumes). Drivers opt in by implementing Replace(ctx, oldRef, spec) → (*ResourceOutput, error) and take ownership of the full Replace transition.
  • wfctlhelpers.DefaultReplace exported (prior doReplace body), callable directly by drivers that want engine-default Delete-then-Create for a specific spec without a sentinel-error round-trip.
  • Engine-side error-prefix backstop (wrapDriverReplaceError) wraps non-conforming errors with "replace: driver: " for consistent operator attribution. Conforming prefixes pass through unchanged.
  • ADR 0014 + CHANGELOG entry.

DropletDriver.Replace adoption follows in workflow-plugin-digitalocean PR-3.

Test plan

  • go test ./interfaces/ ./iac/wfctlhelpers/ -v passes
  • golangci-lint run ./interfaces/ ./iac/wfctlhelpers/ — 0 issues
  • Compile-time interface assertion: TestResourceReplacerInterfaceShape
  • Dispatch test: TestDoReplace_DispatchesToReplacerWhenAvailable — Replacer.Replace invoked, DefaultReplace NOT fired
  • Fallback test: TestDoReplace_DefaultReplaceWhenNoReplacerInterface — DefaultReplace fires for non-implementing drivers
  • Backstop tests: TestWrapDriverReplaceError_* — conforming prefixes pass through, non-conforming get wrapped
  • All existing apply_replace_test.go and apply_replace_cascade_test.go tests remain green

🤖 Generated via brainstorming → writing-plans pipeline

intel352 and others added 5 commits May 7, 2026 17:12
Adds the interfaces.ResourceReplacer optional driver interface for
resources requiring orchestration beyond naive Delete-then-Create
(e.g., Droplets with attached Block Storage Volumes). Non-implementing
drivers retain current behavior via DefaultReplace fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renames doReplace body to DefaultReplace (exported) so drivers
implementing ResourceReplacer can delegate specific specs back to
the engine-default Delete-then-Create without a sentinel-error
round-trip. doReplace becomes a thin dispatch wrapper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…prefix backstop

doReplace now probes the driver for interfaces.ResourceReplacer: on
opt-in, the driver's Replace(ctx, oldRef, spec) takes ownership of
the full transition; non-opt-in drivers continue via DefaultReplace.

Error-prefix backstop wraps non-conforming driver errors with
"replace: driver: " so operator attribution is preserved regardless
of per-plugin error-wrapping discipline. Conforming errors (starting
with "replace:" or "<word> replace ") pass through unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ceErrorPrefix

Adds apply_replacer_prefix_test.go covering all branches of
wrapDriverReplaceError and hasReplaceErrorPrefix: "replace:" family
pass-through, driver-owned "<word> replace " family, non-conforming
backstop wrapping, and nil pass-through.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 7, 2026 21:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in ResourceReplacer driver hook to let IaC resource drivers own the full Replace transition when Delete-then-Create is insufficient (e.g., single-attach dependents), while preserving engine-default behavior for all existing drivers. Also exports the engine’s default Replace implementation for reuse by drivers and adds docs/tests around dispatch and error-prefix attribution.

Changes:

  • Introduce interfaces.ResourceReplacer optional interface (Replace(ctx, oldRef, spec)) for driver-owned Replace orchestration.
  • Export wfctlhelpers.DefaultReplace and route doReplace through the driver hook when available, with an error-prefix backstop wrapper.
  • Add ADR 0014 + changelog entry; add unit tests for dispatch and error-prefix handling.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
interfaces/iac_resource_driver.go Adds the ResourceReplacer optional driver interface with behavioral/error-prefix contract notes.
interfaces/iac_resource_driver_test.go Adds compile-time interface shape assertion for ResourceReplacer.
iac/wfctlhelpers/apply.go Exports DefaultReplace, adds doReplace dispatch to ResourceReplacer, and implements error-prefix backstop helpers.
iac/wfctlhelpers/apply_replacer_prefix_test.go Adds tests for accepted error-prefix families and backstop wrapping behavior.
iac/wfctlhelpers/apply_replacer_dispatch_test.go Adds tests verifying replacer dispatch vs fallback, but one test currently under-asserts intended behavior.
decisions/0014-resource-replacer-driver-interface.md Adds ADR documenting motivation, decision, and consequences for the new hook.
CHANGELOG.md Documents the new interface and exported DefaultReplace.

Comment on lines +89 to +96
err := doReplace(context.Background(), d, action, result)
if err == nil {
t.Fatal("expected error from failing Replacer")
}
// After Task 11 lands, this will assert "replace: driver: kaboom".
// For now assert only that an error was returned (pre-Task-11 compilation).
if err.Error() == "" {
t.Error("error message is empty")
Comment thread iac/wfctlhelpers/apply.go Outdated
Comment on lines +517 to +521
// head must be one alphanumeric token (no spaces, no colons).
for _, r := range head {
if r == ' ' || r == ':' {
return false
}
- `iac/wfctlhelpers/apply.go` — `doReplace` dispatch + `DefaultReplace` + `wrapDriverReplaceError`.
- `iac/wfctlhelpers/apply_replacer_dispatch_test.go` — dispatch tests.
- `iac/wfctlhelpers/apply_replacer_prefix_test.go` — prefix backstop tests.
- core-dump decisions/0010 — canonical source for this decision.
- Strengthened TestDoReplace_ReplacerError_IsWrappedByBackstop to assert
  the 'replace: driver: ' backstop prefix on non-conforming driver errors
  (removed stale pre-Task-11 placeholder comment)
- Clarified hasReplaceErrorPrefix comment: head is a single no-space/no-colon
  token (not strictly alphanumeric — hyphens/underscores/dots accepted)
- Fixed ADR 0014 cross-reference to point to local decisions/0010 file
  instead of ambiguous out-of-repo reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:260: parsing iteration count: invalid syntax
baseline-bench.txt:311271: parsing iteration count: invalid syntax
baseline-bench.txt:597241: parsing iteration count: invalid syntax
baseline-bench.txt:925721: parsing iteration count: invalid syntax
baseline-bench.txt:1270080: parsing iteration count: invalid syntax
baseline-bench.txt:1596280: parsing iteration count: invalid syntax
benchmark-results.txt:260: parsing iteration count: invalid syntax
benchmark-results.txt:357063: parsing iteration count: invalid syntax
benchmark-results.txt:697519: parsing iteration count: invalid syntax
benchmark-results.txt:1020938: parsing iteration count: invalid syntax
benchmark-results.txt:1349856: parsing iteration count: invalid syntax
benchmark-results.txt:1683823: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4              3.399m ± 204%
ComponentLoad-4                    3.713m ±   1%
ComponentExecute-4                 1.959µ ±   1%
PoolContention/workers-1-4         1.105µ ±   1%
PoolContention/workers-2-4         1.122µ ±   2%
PoolContention/workers-4-4         1.105µ ±   2%
PoolContention/workers-8-4         1.109µ ±   1%
PoolContention/workers-16-4        1.112µ ±   1%
ComponentLifecycle-4               3.680m ±   1%
SourceValidation-4                 2.284µ ±   2%
RegistryConcurrent-4               815.8n ±   4%
LoaderLoadFromString-4             3.787m ±   2%
geomean                            17.90µ

                            │ baseline-bench.txt │
                            │        B/op        │
InterpreterCreation-4               2.027Mi ± 0%
ComponentLoad-4                     2.180Mi ± 0%
ComponentExecute-4                  1.203Ki ± 0%
PoolContention/workers-1-4          1.203Ki ± 0%
PoolContention/workers-2-4          1.203Ki ± 0%
PoolContention/workers-4-4          1.203Ki ± 0%
PoolContention/workers-8-4          1.203Ki ± 0%
PoolContention/workers-16-4         1.203Ki ± 0%
ComponentLifecycle-4                2.183Mi ± 0%
SourceValidation-4                  1.984Ki ± 0%
RegistryConcurrent-4                1.133Ki ± 0%
LoaderLoadFromString-4              2.182Mi ± 0%
geomean                             15.25Ki

                            │ baseline-bench.txt │
                            │     allocs/op      │
InterpreterCreation-4                15.68k ± 0%
ComponentLoad-4                      18.02k ± 0%
ComponentExecute-4                    25.00 ± 0%
PoolContention/workers-1-4            25.00 ± 0%
PoolContention/workers-2-4            25.00 ± 0%
PoolContention/workers-4-4            25.00 ± 0%
PoolContention/workers-8-4            25.00 ± 0%
PoolContention/workers-16-4           25.00 ± 0%
ComponentLifecycle-4                 18.07k ± 0%
SourceValidation-4                    32.00 ± 0%
RegistryConcurrent-4                  2.000 ± 0%
LoaderLoadFromString-4               18.06k ± 0%
geomean                               183.3

cpu: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 3.001m ± 189%
ComponentLoad-4                       3.511m ±  11%
ComponentExecute-4                    1.825µ ±   1%
PoolContention/workers-1-4            1.019µ ±   2%
PoolContention/workers-2-4            1.026µ ±   3%
PoolContention/workers-4-4            1.016µ ±   1%
PoolContention/workers-8-4            1.020µ ±   4%
PoolContention/workers-16-4           1.022µ ±   5%
ComponentLifecycle-4                  3.477m ±   3%
SourceValidation-4                    2.096µ ±   3%
RegistryConcurrent-4                  744.1n ±   5%
LoaderLoadFromString-4                3.507m ±   0%
geomean                               16.49µ

                            │ benchmark-results.txt │
                            │         B/op          │
InterpreterCreation-4                  2.027Mi ± 0%
ComponentLoad-4                        2.180Mi ± 0%
ComponentExecute-4                     1.203Ki ± 0%
PoolContention/workers-1-4             1.203Ki ± 0%
PoolContention/workers-2-4             1.203Ki ± 0%
PoolContention/workers-4-4             1.203Ki ± 0%
PoolContention/workers-8-4             1.203Ki ± 0%
PoolContention/workers-16-4            1.203Ki ± 0%
ComponentLifecycle-4                   2.183Mi ± 0%
SourceValidation-4                     1.984Ki ± 0%
RegistryConcurrent-4                   1.133Ki ± 0%
LoaderLoadFromString-4                 2.182Mi ± 0%
geomean                                15.25Ki

                            │ benchmark-results.txt │
                            │       allocs/op       │
InterpreterCreation-4                   15.68k ± 0%
ComponentLoad-4                         18.02k ± 0%
ComponentExecute-4                       25.00 ± 0%
PoolContention/workers-1-4               25.00 ± 0%
PoolContention/workers-2-4               25.00 ± 0%
PoolContention/workers-4-4               25.00 ± 0%
PoolContention/workers-8-4               25.00 ± 0%
PoolContention/workers-16-4              25.00 ± 0%
ComponentLifecycle-4                    18.07k ± 0%
SourceValidation-4                       32.00 ± 0%
RegistryConcurrent-4                     2.000 ± 0%
LoaderLoadFromString-4                  18.06k ± 0%
geomean                                  183.3

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 7763 64-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  293.8n ± 3%
CircuitBreakerExecution_Success-4          21.53n ± 0%
CircuitBreakerExecution_Failure-4          66.34n ± 1%
geomean                                    74.86n

                                  │ baseline-bench.txt │
                                  │        B/op        │
CircuitBreakerDetection-4                 144.0 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │
                                  │     allocs/op      │
CircuitBreakerDetection-4                 1.000 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     298.5n ± 6%
CircuitBreakerExecution_Success-4             22.69n ± 2%
CircuitBreakerExecution_Failure-4             71.20n ± 1%
geomean                                       78.42n

                                  │ benchmark-results.txt │
                                  │         B/op          │
CircuitBreakerDetection-4                    144.0 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

                                  │ benchmark-results.txt │
                                  │       allocs/op       │
CircuitBreakerDetection-4                    1.000 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 7763 64-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     880.7n ± 27%
JQTransform_ObjectConstruction-4         1.464µ ±  1%
JQTransform_ArraySelect-4                3.340µ ±  1%
JQTransform_Complex-4                    38.67µ ±  1%
JQTransform_Throughput-4                 1.767µ ±  1%
SSEPublishDelivery-4                     71.02n ±  5%
geomean                                  1.660µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.22Ki ± 0%
JQTransform_Throughput-4               1.984Ki ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │
                                 │     allocs/op      │
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    324.0 ± 0%
JQTransform_Throughput-4                 17.00 ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        816.6n ± 36%
JQTransform_ObjectConstruction-4            1.411µ ±  2%
JQTransform_ArraySelect-4                   3.359µ ±  2%
JQTransform_Complex-4                       41.05µ ±  1%
JQTransform_Throughput-4                    1.726µ ±  0%
SSEPublishDelivery-4                        63.35n ±  1%
geomean                                     1.609µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
JQTransform_Simple-4                      1.273Ki ± 0%
JQTransform_ObjectConstruction-4          1.773Ki ± 0%
JQTransform_ArraySelect-4                 2.625Ki ± 0%
JQTransform_Complex-4                     16.22Ki ± 0%
JQTransform_Throughput-4                  1.984Ki ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                 │ benchmark-results.txt │
                                 │       allocs/op       │
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       324.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 7763 64-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                    1.095µ ± 1%
SchemaValidation_AllFields-4                 1.667µ ± 2%
SchemaValidation_FormatValidation-4          1.580µ ± 1%
SchemaValidation_ManySchemas-4               1.810µ ± 3%
geomean                                      1.511µ

                                    │ baseline-bench.txt │
                                    │        B/op        │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │
                                    │     allocs/op      │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                       1.114µ ± 5%
SchemaValidation_AllFields-4                    1.651µ ± 3%
SchemaValidation_FormatValidation-4             1.604µ ± 1%
SchemaValidation_ManySchemas-4                  1.603µ ± 1%
geomean                                         1.474µ

                                    │ benchmark-results.txt │
                                    │         B/op          │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

                                    │ benchmark-results.txt │
                                    │       allocs/op       │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 7763 64-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.204µ ± 22%
EventStoreAppend_SQLite-4                  1.398m ±  8%
GetTimeline_InMemory/events-10-4           13.43µ ±  2%
GetTimeline_InMemory/events-50-4           75.96µ ±  2%
GetTimeline_InMemory/events-100-4          120.0µ ±  1%
GetTimeline_InMemory/events-500-4          614.5µ ±  1%
GetTimeline_InMemory/events-1000-4         1.260m ±  0%
GetTimeline_SQLite/events-10-4             106.2µ ±  1%
GetTimeline_SQLite/events-50-4             247.2µ ±  2%
GetTimeline_SQLite/events-100-4            415.9µ ±  2%
GetTimeline_SQLite/events-500-4            1.774m ±  0%
GetTimeline_SQLite/events-1000-4           3.462m ±  0%
geomean                                    216.7µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  768.0 ± 6%
EventStoreAppend_SQLite-4                  1.982Ki ± 3%
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%
geomean                                    67.18Ki

                                   │ baseline-bench.txt │
                                   │     allocs/op      │
EventStoreAppend_InMemory-4                  7.000 ± 0%
EventStoreAppend_SQLite-4                    53.00 ± 0%
GetTimeline_InMemory/events-10-4             125.0 ± 0%
GetTimeline_InMemory/events-50-4             653.0 ± 0%
GetTimeline_InMemory/events-100-4           1.306k ± 0%
GetTimeline_InMemory/events-500-4           6.514k ± 0%
GetTimeline_InMemory/events-1000-4          13.02k ± 0%
GetTimeline_SQLite/events-10-4               382.0 ± 0%
GetTimeline_SQLite/events-50-4              1.852k ± 0%
GetTimeline_SQLite/events-100-4             3.681k ± 0%
GetTimeline_SQLite/events-500-4             18.54k ± 0%
GetTimeline_SQLite/events-1000-4            37.29k ± 0%
geomean                                     1.162k

cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.092µ ± 24%
EventStoreAppend_SQLite-4                     1.066m ±  7%
GetTimeline_InMemory/events-10-4              12.73µ ±  2%
GetTimeline_InMemory/events-50-4              70.90µ ±  3%
GetTimeline_InMemory/events-100-4             108.4µ ± 31%
GetTimeline_InMemory/events-500-4             553.5µ ±  3%
GetTimeline_InMemory/events-1000-4            1.135m ±  1%
GetTimeline_SQLite/events-10-4                84.03µ ±  1%
GetTimeline_SQLite/events-50-4                221.6µ ±  0%
GetTimeline_SQLite/events-100-4               388.7µ ±  3%
GetTimeline_SQLite/events-500-4               1.695m ±  2%
GetTimeline_SQLite/events-1000-4              3.321m ±  2%
geomean                                       194.4µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     775.5 ± 8%
EventStoreAppend_SQLite-4                     1.987Ki ± 2%
GetTimeline_InMemory/events-10-4              7.953Ki ± 0%
GetTimeline_InMemory/events-50-4              46.62Ki ± 0%
GetTimeline_InMemory/events-100-4             94.48Ki ± 0%
GetTimeline_InMemory/events-500-4             472.8Ki ± 0%
GetTimeline_InMemory/events-1000-4            944.3Ki ± 0%
GetTimeline_SQLite/events-10-4                16.74Ki ± 0%
GetTimeline_SQLite/events-50-4                87.14Ki ± 0%
GetTimeline_SQLite/events-100-4               175.4Ki ± 0%
GetTimeline_SQLite/events-500-4               846.1Ki ± 0%
GetTimeline_SQLite/events-1000-4              1.639Mi ± 0%
geomean                                       67.25Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 0%
GetTimeline_InMemory/events-10-4                125.0 ± 0%
GetTimeline_InMemory/events-50-4                653.0 ± 0%
GetTimeline_InMemory/events-100-4              1.306k ± 0%
GetTimeline_InMemory/events-500-4              6.514k ± 0%
GetTimeline_InMemory/events-1000-4             13.02k ± 0%
GetTimeline_SQLite/events-10-4                  382.0 ± 0%
GetTimeline_SQLite/events-50-4                 1.852k ± 0%
GetTimeline_SQLite/events-100-4                3.681k ± 0%
GetTimeline_SQLite/events-500-4                18.54k ± 0%
GetTimeline_SQLite/events-1000-4               37.29k ± 0%
geomean                                        1.162k

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

@intel352 intel352 merged commit d656bcf into main May 7, 2026
23 checks passed
@intel352 intel352 deleted the feat/resource-replacer-interface branch May 7, 2026 21:29
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.

2 participants