Hey everyone!
I'm in the process of cracking event sourcing for DA for my needs (e.g. swift-chat), which then want to decouple and create a separate package out of it.
Here are a bit more information on the topic.
So far I'm trying to replicate Akka's EventSourcedBehavior
, currently idea is that there will be a protocol:
public protocol EventSourced: Codable, DistributedActor where ActorSystem == ClusterSystem {
associatedtype State: Codable & Sendable
associatedtype Command: Codable & Sendable
associatedtype Event: Codable & Sendable
var state: State { get set }
var persistenceId: PersistenceId { get }
distributed func handle(command: Command) async throws -> Event
distributed func handle(event: Event) async throws
}
which then can be applied to actors, e.g.
distributed actor SomeActor: EventSourced {
struct State: Codable, Sendable {
mutating func change() {}
}
enum Event: Codable, Sendable {
case none
}
enum Command: Codable, Sendable {
case none
}
let persistenceId: PersistenceId = "Some"
var state: State = State()
distributed func handle(event: Event) { self.state.change() }
distributed func handle(command: Command) -> Event { Event.none }
}
(note: will continue on improving that, e.g. currently it's not obvious handle(event:)
should be applied to state)
But here where I'm struggling a bit, cause in Akka you just call Effect.persist(event)
and it will do trick for you to persist event. And as I don't have much experience in Akka—not even sure how it's implemented under the hood. currently slowly reading the documentation and code.
What I have in my mind is that in order to declare EventSourced
actors you should register EventJournal
plugin (like it's done with ClusterSingleton
s) like $0.plugins.install(plugin: EventJournal(.postrgres(config)))
with some magic behind. And then somehow declare func persist(event:)
function for actor...
Another question I'm wondering about—I guess this also could be applied to non-distributed actors, where you can just create a separate journal in iOS/macOS/etc and add actors to it.
So if anyone have some suggestions or ideas—would be nice to hear. Also if someone can point to some article or implementation would be also nice to check.