Skip to content

Add actor system built on gumbo shared log#1

Merged
contrasam merged 8 commits into
mainfrom
claude/actor-system-shared-log-eyQXP
Apr 12, 2026
Merged

Add actor system built on gumbo shared log#1
contrasam merged 8 commits into
mainfrom
claude/actor-system-shared-log-eyQXP

Conversation

@contrasam
Copy link
Copy Markdown
Contributor

Three actor flavours backed by gumbo (shared append-only log via JitPack):

  • StatelessActor – pure message handler, no log interaction
  • EventSourcedActor<S,E,M> – events written to bayou.events:; full
    replay on restart reconstructs state
  • StatefulActor<S,M> – (state, message) -> state reducer; periodic
    snapshots to bayou.snapshots:; latest
    snapshot restored on restart (no full replay)

Each actor runs on a virtual thread with a LinkedBlockingQueue mailbox.
BayouSystem is the entry point; ActorRef provides tell/ask/stop.
JavaSerializer ships as a default BayouSerializer (Java serialization).
Tests cover message ordering, ask/reply, replay, snapshot restore,
error rollback, and lifecycle hooks.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY

claude added 8 commits April 12, 2026 18:14
Three actor flavours backed by gumbo (shared append-only log via JitPack):

- StatelessActor<M>          – pure message handler, no log interaction
- EventSourcedActor<S,E,M>   – events written to bayou.events:<id>; full
                               replay on restart reconstructs state
- StatefulActor<S,M>         – (state, message) -> state reducer; periodic
                               snapshots to bayou.snapshots:<id>; latest
                               snapshot restored on restart (no full replay)

Each actor runs on a virtual thread with a LinkedBlockingQueue mailbox.
BayouSystem is the entry point; ActorRef provides tell/ask/stop.
JavaSerializer<T> ships as a default BayouSerializer (Java serialization).
Tests cover message ordering, ask/reply, replay, snapshot restore,
error rollback, and lifecycle hooks.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
- StatelessActor<M> is now Actor<M> throughout (BayouSystem, runner, tests)
- StatelessActor kept as @deprecated(forRemoval=true) alias for compatibility
- README covers setup, all three actor flavours with code examples,
  tell/ask/stop semantics, serialization, and gumbo log tag mapping

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
Runs mvn verify (compile + test) on push to main/claude/**/feature/**
and on pull requests to main. Uses Temurin 21 with Maven cache.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
CI blocker:
- BayouContextImpl: add missing import java.util.concurrent.CompletableFuture

Correctness:
- BayouSystem.shutdown(): wrap allOf().join() in try/finally so
  sharedLog.close() is always called even if an actor stop fails
- AbstractActorRunner: clear currentEnvelope to null after each dispatch
  to prevent stale reply() calls from background threads

API additions:
- ActorRef.isAlive(): liveness check backed by runner's AtomicBoolean
- ActorRef.ask(M, Duration): timeout overload via default method + orTimeout()
- BayouSystem.lookup(String): retrieve a previously spawned ActorRef by ID

Test fixes:
- StatelessActorTest: remove unused ArrayList/List imports
- StatelessActorTest: strengthen preStart/postStop assertion to containsExactly
- All test files: bump Awaitility + get() timeouts from 2s → 5s for CI

New tests:
- EventSourcedActorTest: postStopCalledAfterStop
- StatefulActorTest: snapshotIntervalZeroThrows
- InterActorTest: actor spawning child, lookup, isAlive, ask with timeout

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
- InterActorTest: add explicit <String> type witness on nested spawn() call
  so the lambda parameter is correctly typed as String not Object
- InterActorTest: use var for lookup("no-such-actor") to avoid
  unchecked Optional<ActorRef<M>> -> Optional<ActorRef<?>> conversion
- StatefulActorTest: replace StatefulActor<> diamond with explicit
  StatefulActor<Tally, TallyCmd> on both anonymous class sites so
  reduce() override is recognized correctly

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
…variable

The explicit type witness <String> on a chained call inside an outer
lambda does not propagate type info reliably across javac versions.
Splitting into Actor<String> childActor + spawn(id, childActor) makes
the type parameter unambiguous without any type witness.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
…level call

Move the <String> type witness to the outer system.spawn() call, which is
at statement level (not nested inside another lambda), where javac reliably
propagates M=String into the lambda parameter msg.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
…et typing

Pattern matches StatelessActorTest: ActorRef<String> ref = system.spawn(...)
gives javac a concrete target type so msg is inferred as String.
Also simplifies test by using ref directly instead of lookup.

https://claude.ai/code/session_016Sdv7MqPBFN2wt65ohRFcY
@contrasam contrasam merged commit b25300f into main Apr 12, 2026
2 checks passed
@contrasam contrasam deleted the claude/actor-system-shared-log-eyQXP branch April 12, 2026 18:45
contrasam added a commit that referenced this pull request Apr 13, 2026
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