Skip to content

build(deps): bump github.com/tochemey/goakt/v4 from 4.1.1 to 4.2.2#420

Merged
intel352 merged 2 commits into
mainfrom
dependabot/go_modules/github.com/tochemey/goakt/v4-4.2.1
May 5, 2026
Merged

build(deps): bump github.com/tochemey/goakt/v4 from 4.1.1 to 4.2.2#420
intel352 merged 2 commits into
mainfrom
dependabot/go_modules/github.com/tochemey/goakt/v4-4.2.1

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Apr 20, 2026

Copy link
Copy Markdown
Contributor

Bumps github.com/tochemey/goakt/v4 from 4.1.1 to 4.2.2.

Release notes

Sourced from github.com/tochemey/goakt/v4's releases.

v4.2.2

A shutdown-hardening and hot-path performance patch on top of v4.2.1. One new option, three hot-path wins, and a cluster of race/panic fixes in the actor-system shutdown path.

New

  • WithThroughputBudget option. Makes the dispatcher's per-turn message budget user-tunable. Default remains 32. Raise it to amortise scheduling overhead on hot actors; lower it for tail-latency fairness under many-small-actor workloads. Per-actor FIFO and the single-threaded-per-actor invariant are preserved — a yield is a pause, not a reorder.

Performance

Gains below are allocation counts (architectural, machine-independent). Throughput and latency impact will vary per machine and workload — measure on your own hardware.

  • Allocation-free local dispatch. UnboundedMailbox and grainMailbox now embed the MPSC next pointer directly on *ReceiveContext / *GrainContext, retiring the separate node struct and its pool. grainPID's activity timestamp moves from go.uber.org/atomic.Time to a stdlib atomic.Int64. Tell / SendAsync drop from 1 → 0 allocs/op; GrainTell, GrainTellFanOut, and GrainAsk drop from 24 B/op, 1 allocs/op to 0 B/op, 0 allocs/op.
  • Pooled output frames on remote Tell. The outbound encoder in internal/net now draws from the existing FramePool on both client and server, closing the last reflective make([]byte, 0, totalLen) allocation on the send path. Wire format unchanged. Bytes allocated per message drop ~15% on the remote-Tell throughput benchmark.

Fixes

Actor-system shutdown hardening (PR #1163)

  • Data race on segment.deqIdx and head in UnboundedSegmentedMailbox under cross-worker handoff. When the dispatcher hands mailbox ownership from one worker to another, the outgoing worker's IsEmpty (via finishOrReclaim) collided with the incoming worker's Dequeue on both fields. Both are now atomic.Uint64 / atomic.Pointer[segment].
  • Dispatcher self-deadlock when ActorSystem.Stop runs from within a worker turn. The old dispatcher.stop() blocked on a sync.WaitGroup until every worker exited; when shutdown was triggered from inside an actor's Receive (or a grain handler) the calling worker waited on its own WaitGroup entry and deadlocked. dispatcher.stop() and its sync.WaitGroup are removed in favour of the fire-and-forget signalStop. Lifecycle goroutines that shutdown must still wait for (replicateActors / replicateGrains) are tracked via a separate drainers sync.WaitGroup.
  • Panic: send on closed channel in putActorOnCluster / putGrainOnCluster. Both helpers unconditionally sent on actorsQueue / grainsQueue; any in-flight spawn arriving after shutdown closed those channels panicked the process. Each send is now gated by the shuttingDown atomic, with a deferred recover for the narrow TOCTOU window where the flag still reads false but the channel closes between the check and the send.

Other fixes

  • Data race on the ejected-sentinel next field in UnboundedMailbox.Dequeue. Dequeue reset the previous sentinel's next with a plain assignment while IsEmpty / Len atomically loaded it. The reset is now an atomic.StorePointer.
  • Worker-pool cleanup off-by-one leaked one idle worker per pass under the small-list path. A for j = 0; j < iws; j++for j = range iws modernisation in internal/net.WorkerPool.cleanup shifted the post-loop j, leaving the last expired worker behind on every tick. Reverted to the explicit C-style loop.
  • Metadata zero-copy lifetime bug under pooled frames. internal/net.Metadata.UnmarshalBinary aliased the caller-supplied byte slice via unsafe.String; with the write path now drawing from the same FramePool, the buffer could be recycled while the handler still held those strings. Replaced with explicit string(data[...]) copies.

Improvements

  • Removed dead stash-release bookkeeping. ReceiveContext.stashed, ctx.Stash()'s stashed.Store(true) call, and the obsolete releaseContext helper are gone. dispatchOne on both actor and grain paths drops its unused retained bool return. Observable stash semantics are unchanged.

Upgrade notes

  • No public API changes. Wire format is unchanged.
  • WithThroughputBudget is additive — existing applications keep the 32-message default with no code change.
  • The removal of dispatcher.stop() is internal; ActorSystem.Stop callers are unaffected and now safe to invoke from within a worker turn.

Pull Requests

New Contributors

Full changelog

... (truncated)

Changelog

Sourced from github.com/tochemey/goakt/v4's changelog.

v4.2.2 - 2026-04-24

✨ New Additions

  • WithThroughputBudget option — tunable dispatcher per-turn message budget. Exposes the dispatcher's per-turn message budget (the maximum number of messages a worker drains from a single actor before yielding back to the scheduler) as a user-configurable ActorSystem option. The default remains 32, chosen for balanced fairness across many actors; raising it amortises per-turn scheduling overhead and keeps CPU caches warm on hot actors at the cost of fairness, and lowering it favours tail-latency predictability under many-small-actor workloads. Per-actor FIFO ordering and the single-threaded-per-actor execution invariant are preserved regardless of the value — a yield is a pause, not a reorder. Variant benchmarks — BenchmarkTellThroughput, BenchmarkRequestThroughput, BenchmarkSendSyncThroughput, BenchmarkGrainTellThroughput, BenchmarkGrainTellFanOutThroughput — sweep the budget across {8, 32, 64, 128, 256} so users can measure impact on their own workload. Measured on Apple M1, the default is near-optimal on typical workloads; fan-out workloads see ~2-5% aggregate gains at 64-128 and a mild regression at 256, confirming the fairness cost at very high budgets. See the WithThroughputBudget godoc for guidance per workload class.

🚀 Performance

  • Pooled output frames on the remote-Tell send path. The outbound encoder in internal/net now draws its output buffer from the existing FramePool (previously used only on the read side) and returns it to the pool after conn.Write. This closes the last reflective-make([]byte, 0, totalLen) hot-path allocation on the client encode and server response paths. The public ProtoSerializer.MarshalBinary and MarshalBinaryWithMetadata APIs are unchanged; new *To variants accept an optional *FramePool and form the pooled fast path used by Client and ProtoServer. Wire format is unchanged. Measured on Apple M1 with the BenchmarkRemoteTellThroughput configuration (20 senders / 10 engines / 2000 actors over localhost): bytes allocated per message 507 → 427 (−15.8%) with throughput flat within run-to-run variance. ProtoSerializer.MarshalBinary drops from 13.8% of allocated bytes to not appearing in the top allocators at all.
  • Intrusive mailboxes — allocation-free local dispatch hot path. UnboundedMailbox and grainMailbox now use their payload types (*ReceiveContext / *GrainContext) directly as the MPSC linked-list node via an unexported next field, retiring the separate node struct and its dedicated pool on both paths. Under sustained producer-faster-than-consumer load, peak in-flight message count vastly exceeds any fixed pool size, so the old design churned through new(node) per message once the pool saturated — dominating GC CPU time. Collapsing the two-pool design into one eliminates that half of the churn, and the remaining ReceiveContext / GrainContext pool is now the only allocation surface on the hot path. On the grain side, grainPID's activity timestamp also moves from go.uber.org/atomic.Time (boxed through atomic.Value) to a stdlib atomic.Int64 holding UnixNano, removing the per-message allocation inside markActivity. Net result — machine-independent: the Tell / SendAsync benchmarks drop from 1 to 0 reported allocs/op under the bench harness; BenchmarkGrainTell, BenchmarkGrainTellFanOut, and BenchmarkGrainAsk drop from 24 B/op, 1 allocs/op to 0 B/op, 0 allocs/op. Absolute throughput gains are workload- and hardware-dependent; the architectural property is that the hot path no longer allocates, so GC cost scales with application logic, not with message rate. A payload type is linked into at most one mailbox at a time; the stash path therefore copies across mailboxes via a new cloneContext (slow path, not on dispatch). Public ReceiveContext, GrainContext, Mailbox, UnboundedMailbox, and grainMailbox constructors and method signatures are unchanged.

🐛 Fixes

  • Worker-pool cleanup off-by-one — leaked one idle worker per pass under the small-list path. A recent modernisation of internal/net.WorkerPool.cleanup swapped the small-list reap loop from for j = 0; j < iws; j++ to for j = range iws; the two forms differ in post-loop j value (iws vs iws - 1), so the reap prefix idleWorkerList[:j] left the last expired worker behind on every cleanup tick. Once the list reached a single stuck entry the if j == 0 { continue } early-out skipped it forever, leaking worker goroutines. Reverted to the explicit C-style form with a comment documenting the hazard so the linter's "modernize using range over int" suggestion does not re-trigger it. The binary-search branch (iws > 400) was unaffected. Covered by TestWorkerPool_Cleanup and TestWorkerPool_CleanupIdleWorkerSlots, which had been silently failing.
  • Metadata zero-copy lifetime bug under pooled frames. internal/net.Metadata.UnmarshalBinary extracted header keys and values via unsafe.String pointers that aliased the caller-supplied byte slice. On the server path that slice is a pooled request frame returned to the FramePool before the handler runs — with the write path also now drawing from the same pool, the buffer can be recycled and overwritten while the handler is still holding those metadata strings, corrupting their bytes. Replaced the zero-copy extraction with explicit string(data[...]) copies; metadata payloads are small (a few headers per call) and the allocation cost is negligible compared to the correctness win. No public API change.
  • Data race on the ejected-sentinel next field in UnboundedMailbox.Dequeue. Dequeue reset the previous sentinel's next with a plain assignment while IsEmpty / Len (also reachable via finishOrReclaim) atomically load that same field. Because finishOrReclaim resets schedState before calling IsEmpty, a sibling worker may enter Dequeue on the same PID concurrently and the two accesses collide. The reset is now an atomic.StorePointer. Caught by TestMessageOrdering under -race; no throughput impact since the producer side already used an atomic store on the same field.
  • Data race on segment.deqIdx and head in UnboundedSegmentedMailbox under cross-worker mailbox handoff. The segment's dequeue index (plain uint64) and the mailbox's head pointer (plain *segment) were written by the consumer in Dequeue and read by IsEmpty. When the dispatcher pool hands mailbox ownership from one worker to another, the outgoing worker may call IsEmpty via finishOrReclaim while the incoming worker begins Dequeue, colliding on both fields. Both are now atomic.Uint64 and atomic.Pointer[segment] respectively. Covered by a new TestUnboundedSegmentedMailbox_CrossWorkerHandoff under -race; no throughput impact since the producer side already used the matching atomic stores.
  • Dispatcher self-deadlock when ActorSystem.Stop is invoked from within a worker turn. The old dispatcher.stop() blocked on a sync.WaitGroup until every worker exited; when shutdown was triggered from inside an actor's Receive (or a grain's handler), the calling worker waited on its own WaitGroup entry and deadlocked the system. dispatcher.stop() and its internal sync.WaitGroup have been removed in favour of the fire-and-forget signalStop, which closes the ready queue and wakes parked workers without blocking the caller — each worker drains its current turn and exits on its own. Lifecycle goroutines that shutdown must still wait for (replicateActors / replicateGrains) are tracked via a separate drainers sync.WaitGroup so reset can safely reassign shutdownSignal. Covered by the updated dispatcher tests.
  • Panic: send on closed channel in putActorOnCluster / putGrainOnCluster. Both cluster-publication helpers unconditionally sent on actorsQueue / grainsQueue; the shutdown path closes those channels under a single-shot shuttingDown CAS, and any in-flight spawn arriving after the close panicked the process. Each send is now gated by the shuttingDown atomic flag, with a deferred recover to absorb the narrow TOCTOU window where the flag still reads false but the channel closes between the check and the send. Shutdown now also waits on the replicate drainers before letting reset() reassign shutdownSignal, so late pushes can no longer observe a half-rebuilt actor system.

🔧 Improvements

  • Removed dead stash-release bookkeeping. Moving context release into UnboundedMailbox.Dequeue (see the intrusive-mailbox entry) eliminated the sole reader of ReceiveContext.stashed. The field, the stashed.Store(true) call inside ctx.Stash(), and the obsolete releaseContext helper are gone; dispatchOne on both actor and grain paths drops its unused retained bool return. Observable stash semantics are unchanged (covered by the full TestStash / TestReentrancy suites under -race).
  • Benchmark suite measures end-to-end delivery. BenchmarkTell, BenchmarkSendAsync, BenchmarkGrainTell, BenchmarkGrainTellFanOut, and all *Throughput variants now use a counting actor/grain with a done-channel signal and wait for the receiver to drain b.N messages before stopping the timer. Fan-out benchmarks hold a per-grain private counter instead of a single shared atomic so the measurement itself adds no cross-core contention. Previously the clock stopped at the end of the producer loop, which reported enqueue rate under producer-faster-than-consumer conditions rather than delivery rate.

v4.2.1 - 2026-04-16

✨ New Additions

  • Enhanced the testkit package with new helper methods for improved test ergonomics.

🚀 Performance

  • Dispatcher pool — actor scheduling substrate. The per-actor spawn-on-burst drainer goroutine is replaced with a fixed pool of worker goroutines (max(GOMAXPROCS, 2)) that cooperatively multiplex the entire actor population, following the Akka / Pekko / Erlang / Orleans pattern. Each ActorSystem owns one dispatcher; actors are scheduled onto a hybrid ready queue (per-worker 256-slot local rings + shared amortised-FIFO global ring + half-quota work stealing + condvar parking). A worker pulls an actor, drains up to 32 messages per turn, then yields so peers get a turn — bounding the blocking window a single actor can impose and decoupling goroutine count from actor count. A three-state atomic machine (Idle / Scheduled / Processing) on each PID preserves the single-threaded-per-actor execution invariant via a Scheduled → Processing CAS. Every user-visible semantic (FIFO ordering, PreStart / PostStop contract, reentrancy stash, panic recovery, supervision) is unchanged; the only observable difference is that runtime.NumGoroutine() no longer scales with active-actor count. Each actor also gains a dedicated system mailbox that is drained before the user mailbox every turn, so control-plane messages (PoisonPill, supervision, passivation, Terminated, dead-letter routing) cannot queue behind a user-message backlog. See https://github.com/Tochemey/goakt/blob/main/architecture/DISPATCHER_POOL_DESIGN.md.
  • Grains migrated onto the dispatcher pool. grainPID now implements the same schedulable contract as PID and shares the actor system's dispatcher, retiring the per-grain spawn-on-burst drainer goroutine. The single-threaded-per-grain execution invariant is preserved by the same three-state CAS (Idle / Scheduled / Processing) used by actors; worker turns drain up to 32 messages per rotation, with race-safe reclaim on drain and cooperative yield-and-reschedule when the budget is exhausted. Goroutine count is now bounded by GOMAXPROCS regardless of active grain count — at million-grain scale this removes the dominant per-grain goroutine stack overhead. Public Grain, GrainContext, and GrainIdentity semantics are unchanged.
  • Grain send hot path — regex compile elimination. GrainIdentity.Validate() previously recompiled a regex on every TellGrain / AskGrain call; GrainIdentity fields are immutable after construction so the result is now memoised via sync.Once. Profiling had this accounting for ~98% of per-call allocations. Measured on Apple M1 at steady state: allocations per call 51 → 1 (−98%), bytes per call 3,216 → 24 (−99%). Throughput measured end-to-end: TellGrain single-grain +180% (466k → 1.31M msgs/s @ GOMAXPROCS=8), TellGrain fan-out across 256 grains +85% (460k → 850k msgs/s), AskGrain +260% (275k → 988k msgs/s). Actor Tell / Ask paths are untouched — the change is confined to GrainIdentity and the fast-path ensureGrainProcess bypass of singleflight when the grain is already active. Grain-only benchmarks (BenchmarkGrainTell, BenchmarkGrainTellFanOut, BenchmarkGrainAsk) added to the benchmark package.
  • Send coalescing for Tell to remote actors. When Tell (via actor.Tell, *PID.Tell, or ReceiveContext.Tell) targets a remote *PID, the outbound transport path now uses a per-destination Nagle-style writer that amortizes per-RPC cost across messages that pile up while a previous send is in flight. A single message against an idle destination is still sent immediately — batching happens only while a send is already in progress, so there is no artificial latency on the happy path. Measured on Apple M1 with 20 senders / 10 engines / 2000 actors and default zstd compression, throughput goes from ~122k msgs/sec to ~880k msgs/sec (~7.2×). The benchmark covering this configuration lives in benchmark/remote_tell_thoughput_test.go.
  • Context propagation is preserved end-to-end for messages sent to remote actors via a new per-message metadata field on the transport-level RemoteMessage, populated by the configured ContextPropagator at enqueue time and applied by the server before dispatching each message.
  • Wire format: internalpb.RemoteMessage gained map<string, string> metadata = 4;. Additive and backward-compatible — older peers ignore the field.

⚠️ Behavior changes

  • Tell is a fire-and-forget one-way send; its returned error still reports failures detected before the message leaves the caller's process (no serializer registered for the message type, already-cancelled context at entry, errors.ErrRemoteSendBackpressure on a saturated outbound queue, errors.ErrRemoteSendFailure for other enqueue-time failures). What changed is that the call now returns once the message has been handed off to the per-destination coalesced writer rather than after the transport ACK, so transport-level failures on sends that have already been batched happen after Tell returns and can no longer appear in the return value; they are logged asynchronously through the actor system's logger instead. Callers that need a reply or delivery confirmation should use Ask against the remote *PID, which is unaffected. Per-call context deadlines set on a remote Tell call are not honored once the message has been batched; the writer uses its own transport deadline.
  • Default remote compression changed from ZstdCompression to NoCompression. This aligns GoAkt with the convention adopted by gRPC, Akka, Erlang distribution, Kafka, and Orleans: transport-level compression is left off by default because typical actor payloads are small structured protobuf for which compression yields little bandwidth savings and meaningful CPU and allocator overhead — particularly on intra-cluster LAN links. Deployments where bandwidth is the binding constraint (cross-region / WAN, large or highly repetitive payloads) should opt in explicitly with remote.WithCompression(remote.ZstdCompression). Both ends of a remote connection must agree on the algorithm, so when upgrading either configure both peers explicitly or upgrade them together.
  • Tell to a remote *PID now applies bounded-queue backpressure when send coalescing is engaged. Previously, when the per-destination writer's input channel was saturated the call silently fell through to a second synchronous connection; under burst load this exposed callers to transport-level errors from connection-pool contention. Behaviour now matches the industry-standard pattern used by Erlang distribution, Akka Artery, Kafka producer, and gRPC streaming: the call blocks on the outbound queue until space becomes available, the caller's context is cancelled, or the transport is shut down. On context deadline/cancel the call returns a new typed error errors.ErrRemoteSendBackpressure (joined with the underlying ctx.Err(), so errors.Is(err, context.DeadlineExceeded) remains true); callers decide whether to retry, drop, or circuit-break. The synchronous fallback path has been removed. This eliminates a class of spurious transport errors under load (benchmarks run during development went from ~500 errors / 10M sends to 0) and makes overload visible as a distinct, actionable signal rather than generic RPC failure. Local Tell and all Ask calls (local or remote) are unaffected.

🔧 Improvements

  • Adjusted the benchmark package name for consistency.
  • Conducted general code cleanup across the codebase.

... (truncated)

Commits
  • 0b88230 docs: update changelog.md to account for latest changes and set release versi...
  • e327161 fix: data races and panics in actor system shutdown path (#1163)
  • c25c31e chore(deps): update module github.com/vektra/mockery/v2 to v3 (#1161)
  • 66256d9 perf: performance improvement (#1159)
  • fc219af docs: realign readme feature section
  • d16ad1c chore: remove earthly dependency
  • 3e194d0 docs: readme badge cleanup
  • 4bbea17 docs(actor): 📝 update the changelog.md
  • a05d294 perf: refactor the proto server implementation (#1158)
  • f9b7f84 style: fix formatting
  • Additional commits viewable in compare view

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file go Pull requests that update go code labels Apr 20, 2026
@github-actions

github-actions Bot commented Apr 20, 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:334809: parsing iteration count: invalid syntax
baseline-bench.txt:602101: parsing iteration count: invalid syntax
baseline-bench.txt:1131362: parsing iteration count: invalid syntax
baseline-bench.txt:1450134: parsing iteration count: invalid syntax
baseline-bench.txt:1731592: parsing iteration count: invalid syntax
benchmark-results.txt:260: parsing iteration count: invalid syntax
benchmark-results.txt:320847: parsing iteration count: invalid syntax
benchmark-results.txt:644416: parsing iteration count: invalid syntax
benchmark-results.txt:992954: parsing iteration count: invalid syntax
benchmark-results.txt:1299714: parsing iteration count: invalid syntax
benchmark-results.txt:1619143: 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 │       benchmark-results.txt        │
                            │       sec/op       │    sec/op     vs base              │
InterpreterCreation-4               7.182m ± 57%   6.475m ± 68%       ~ (p=0.937 n=6)
ComponentLoad-4                     3.594m ±  0%   3.589m ±  2%       ~ (p=0.240 n=6)
ComponentExecute-4                  1.925µ ±  1%   1.927µ ±  1%       ~ (p=0.781 n=6)
PoolContention/workers-1-4          1.085µ ±  3%   1.087µ ±  1%       ~ (p=0.970 n=6)
PoolContention/workers-2-4          1.085µ ±  1%   1.091µ ±  2%       ~ (p=0.567 n=6)
PoolContention/workers-4-4          1.085µ ±  1%   1.090µ ±  0%  +0.51% (p=0.050 n=6)
PoolContention/workers-8-4          1.089µ ±  1%   1.090µ ±  1%       ~ (p=0.381 n=6)
PoolContention/workers-16-4         1.086µ ±  1%   1.100µ ±  4%  +1.29% (p=0.013 n=6)
ComponentLifecycle-4                3.622m ±  1%   3.626m ±  1%       ~ (p=0.310 n=6)
SourceValidation-4                  2.243µ ±  0%   2.267µ ±  1%  +1.05% (p=0.002 n=6)
RegistryConcurrent-4                811.0n ±  3%   837.6n ±  3%       ~ (p=0.061 n=6)
LoaderLoadFromString-4              3.631m ±  0%   3.656m ±  0%  +0.68% (p=0.002 n=6)
geomean                             18.67µ         18.63µ        -0.22%

                            │ baseline-bench.txt │        benchmark-results.txt         │
                            │        B/op        │     B/op      vs base                │
InterpreterCreation-4               2.027Mi ± 0%   2.027Mi ± 0%       ~ (p=0.848 n=6)
ComponentLoad-4                     2.180Mi ± 0%   2.180Mi ± 0%       ~ (p=0.667 n=6)
ComponentExecute-4                  1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4         1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                2.183Mi ± 0%   2.183Mi ± 0%       ~ (p=0.900 n=6)
SourceValidation-4                  1.984Ki ± 0%   1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                1.133Ki ± 0%   1.133Ki ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4              2.182Mi ± 0%   2.182Mi ± 0%       ~ (p=0.240 n=6)
geomean                             15.25Ki        15.25Ki       -0.00%
¹ all samples are equal

                            │ baseline-bench.txt │        benchmark-results.txt        │
                            │     allocs/op      │  allocs/op   vs base                │
InterpreterCreation-4                15.68k ± 0%   15.68k ± 0%       ~ (p=1.000 n=6)
ComponentLoad-4                      18.02k ± 0%   18.02k ± 0%       ~ (p=1.000 n=6)
ComponentExecute-4                    25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4           25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                 18.07k ± 0%   18.07k ± 0%       ~ (p=1.000 n=6) ¹
SourceValidation-4                    32.00 ± 0%    32.00 ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                  2.000 ± 0%    2.000 ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4               18.06k ± 0%   18.06k ± 0%       ~ (p=1.000 n=6) ¹
geomean                               183.3         183.3       +0.00%
¹ all samples are equal

pkg: github.com/GoCodeAlone/workflow/middleware
                                  │ baseline-bench.txt │       benchmark-results.txt       │
                                  │       sec/op       │   sec/op     vs base              │
CircuitBreakerDetection-4                  287.4n ± 4%   285.5n ± 3%  -0.66% (p=0.026 n=6)
CircuitBreakerExecution_Success-4          21.56n ± 0%   21.70n ± 1%       ~ (p=0.084 n=6)
CircuitBreakerExecution_Failure-4          66.22n ± 0%   66.29n ± 2%       ~ (p=0.816 n=6)
geomean                                    74.31n        74.33n       +0.02%

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │        B/op        │    B/op     vs base                │
CircuitBreakerDetection-4                 144.0 ± 0%     144.0 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │     allocs/op      │ allocs/op   vs base                │
CircuitBreakerDetection-4                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │       sec/op       │    sec/op     vs base              │
JQTransform_Simple-4                     882.4n ± 29%   858.0n ± 29%       ~ (p=0.180 n=6)
JQTransform_ObjectConstruction-4         1.457µ ±  1%   1.424µ ±  0%  -2.26% (p=0.002 n=6)
JQTransform_ArraySelect-4                3.347µ ±  1%   3.254µ ±  1%  -2.78% (p=0.002 n=6)
JQTransform_Complex-4                    38.80µ ±  1%   37.67µ ±  2%  -2.92% (p=0.002 n=6)
JQTransform_Throughput-4                 1.790µ ±  1%   1.766µ ±  1%  -1.37% (p=0.004 n=6)
SSEPublishDelivery-4                     75.06n ±  1%   70.50n ±  0%  -6.07% (p=0.002 n=6)
geomean                                  1.679µ         1.628µ        -3.04%

                                 │ baseline-bench.txt │        benchmark-results.txt         │
                                 │        B/op        │     B/op      vs base                │
JQTransform_Simple-4                   1.273Ki ± 0%     1.273Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4       1.773Ki ± 0%     1.773Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4              2.625Ki ± 0%     2.625Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                  16.22Ki ± 0%     16.22Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4               1.984Ki ± 0%     1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²                 +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │     allocs/op      │ allocs/op   vs base                │
JQTransform_Simple-4                     10.00 ± 0%     10.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4         15.00 ± 0%     15.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4                30.00 ± 0%     30.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                    324.0 ± 0%     324.0 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4                 17.00 ± 0%     17.00 ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │       sec/op       │    sec/op     vs base              │
SchemaValidation_Simple-4                    1.113µ ± 3%   1.097µ ±  2%       ~ (p=0.167 n=6)
SchemaValidation_AllFields-4                 1.650µ ± 1%   1.683µ ± 21%       ~ (p=0.290 n=6)
SchemaValidation_FormatValidation-4          1.580µ ± 1%   1.584µ ±  5%       ~ (p=0.677 n=6)
SchemaValidation_ManySchemas-4               1.812µ ± 3%   1.865µ ±  3%       ~ (p=0.084 n=6)
geomean                                      1.514µ        1.528µ        +0.91%

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │        B/op        │    B/op     vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │     allocs/op      │ allocs/op   vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │       sec/op       │    sec/op     vs base               │
EventStoreAppend_InMemory-4                1.241µ ± 18%   1.144µ ± 22%        ~ (p=0.589 n=6)
EventStoreAppend_SQLite-4                  1.545m ±  3%   1.338m ±  6%  -13.42% (p=0.002 n=6)
GetTimeline_InMemory/events-10-4           13.49µ ±  3%   13.41µ ±  3%        ~ (p=0.589 n=6)
GetTimeline_InMemory/events-50-4           76.35µ ±  4%   75.50µ ±  2%        ~ (p=0.240 n=6)
GetTimeline_InMemory/events-100-4          152.7µ ±  2%   132.3µ ± 17%        ~ (p=0.180 n=6)
GetTimeline_InMemory/events-500-4          618.5µ ± 15%   636.9µ ±  1%        ~ (p=0.065 n=6)
GetTimeline_InMemory/events-1000-4         1.261m ±  1%   1.306m ±  1%   +3.55% (p=0.002 n=6)
GetTimeline_SQLite/events-10-4             106.6µ ±  1%   107.5µ ±  1%   +0.82% (p=0.009 n=6)
GetTimeline_SQLite/events-50-4             244.6µ ±  1%   250.7µ ±  0%   +2.48% (p=0.002 n=6)
GetTimeline_SQLite/events-100-4            414.2µ ±  1%   423.9µ ±  0%   +2.33% (p=0.002 n=6)
GetTimeline_SQLite/events-500-4            1.759m ±  1%   1.827m ±  0%   +3.88% (p=0.002 n=6)
GetTimeline_SQLite/events-1000-4           3.449m ±  1%   3.554m ±  0%   +3.03% (p=0.002 n=6)
geomean                                    223.3µ         219.7µ         -1.63%

                                   │ baseline-bench.txt │         benchmark-results.txt         │
                                   │        B/op        │     B/op       vs base                │
EventStoreAppend_InMemory-4                  775.5 ± 6%     779.5 ± 12%       ~ (p=0.589 n=6)
EventStoreAppend_SQLite-4                  1.987Ki ± 1%   1.984Ki ±  2%       ~ (p=1.000 n=6)
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%   7.953Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%   46.62Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%   94.48Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%   472.8Ki ±  0%       ~ (p=0.182 n=6)
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%   944.3Ki ±  0%       ~ (p=0.076 n=6)
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%   16.74Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%   87.14Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%   175.4Ki ±  0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%   846.1Ki ±  0%  +0.00% (p=0.006 n=6)
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%   1.639Mi ±  0%  -0.00% (p=0.011 n=6)
geomean                                    67.25Ki        67.27Ki        +0.03%
¹ all samples are equal

                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │     allocs/op      │  allocs/op   vs base                │
EventStoreAppend_InMemory-4                  7.000 ± 0%    7.000 ± 0%       ~ (p=1.000 n=6) ¹
EventStoreAppend_SQLite-4                    53.00 ± 0%    53.00 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-10-4             125.0 ± 0%    125.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4             653.0 ± 0%    653.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4           1.306k ± 0%   1.306k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4           6.514k ± 0%   6.514k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-1000-4          13.02k ± 0%   13.02k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-10-4               382.0 ± 0%    382.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4              1.852k ± 0%   1.852k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4             3.681k ± 0%   3.681k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4             18.54k ± 0%   18.54k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-1000-4            37.29k ± 0%   37.29k ± 0%       ~ (p=1.000 n=6) ¹
geomean                                     1.162k        1.162k       +0.00%
¹ all samples are equal

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

@dependabot dependabot Bot changed the title build(deps): bump github.com/tochemey/goakt/v4 from 4.1.1 to 4.2.1 build(deps): bump github.com/tochemey/goakt/v4 from 4.1.1 to 4.2.2 May 3, 2026
@dependabot dependabot Bot force-pushed the dependabot/go_modules/github.com/tochemey/goakt/v4-4.2.1 branch from 57e45b5 to 1530e1c Compare May 3, 2026 02:38
Bumps [github.com/tochemey/goakt/v4](https://github.com/tochemey/goakt) from 4.1.1 to 4.2.2.
- [Release notes](https://github.com/tochemey/goakt/releases)
- [Changelog](https://github.com/Tochemey/goakt/blob/main/CHANGELOG.md)
- [Commits](Tochemey/goakt@v4.1.1...v4.2.2)

---
updated-dependencies:
- dependency-name: github.com/tochemey/goakt/v4
  dependency-version: 4.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot force-pushed the dependabot/go_modules/github.com/tochemey/goakt/v4-4.2.1 branch from 1530e1c to 450a340 Compare May 5, 2026 01:15
@intel352

intel352 commented May 5, 2026

Copy link
Copy Markdown
Contributor

…after goakt v4.2.2 bump

Agent-Logs-Url: https://github.com/GoCodeAlone/workflow/sessions/b4ea455f-d34b-4d9b-90f9-f427775106cc

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>

Copilot AI commented May 5, 2026

Copy link
Copy Markdown
Contributor

@copilot Fix the mod tidy failing pr check https://github.com/GoCodeAlone/workflow/actions/runs/25352605432/job/74335272441?pr=420

Fixed in d7d443e. The example/go.mod and example/go.sum needed to be updated via go mod tidy to reflect the transitive dependency changes from the goakt v4.2.2 bump.

Copilot AI requested a review from intel352 May 5, 2026 07:43
@intel352 intel352 merged commit dd24abc into main May 5, 2026
22 of 23 checks passed
@intel352 intel352 deleted the dependabot/go_modules/github.com/tochemey/goakt/v4-4.2.1 branch May 5, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants