tochemey / goakt Goto Github PK
View Code? Open in Web Editor NEW[Go] Fast and Distributed Actor framework using protocol buffers as message for Golang
License: MIT License
[Go] Fast and Distributed Actor framework using protocol buffers as message for Golang
License: MIT License
The current implementation relies on etcd embedded server. We need to rethink this approach when we want to add cluster sharding and co. The reason is that the replication behind etcd cannot horizontally scale because it lacks data sharding.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
go.opentelemetry.io/otel
, go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
, go.opentelemetry.io/otel/exporters/prometheus
, go.opentelemetry.io/otel/exporters/stdout/stdouttrace
, go.opentelemetry.io/otel/metric
, go.opentelemetry.io/otel/sdk
, go.opentelemetry.io/otel/sdk/metric
, go.opentelemetry.io/otel/trace
, google.golang.org/protobuf
, k8s.io/api
, k8s.io/apimachinery
, k8s.io/client-go
)These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
.github/workflows/build.yml
actions/checkout v4
docker/login-action v3
earthly/actions v1
codecov/codecov-action v4
.github/workflows/pr.yml
actions/checkout v4
docker/login-action v3
earthly/actions v1
codecov/codecov-action v4
go.mod
go 1.21
connectrpc.com/connect v1.16.1
connectrpc.com/otelconnect v0.7.0
github.com/buraksezer/olric v0.5.6-0.20240205222928-c5efb0d4b5ea@c5efb0d4b5ea
github.com/caarlos0/env/v11 v11.0.0
github.com/cespare/xxhash/v2 v2.3.0
github.com/deckarep/golang-set/v2 v2.6.0
github.com/flowchartsman/retry v1.2.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/grandcat/zeroconf v1.0.0
github.com/joho/godotenv v1.5.1
github.com/nats-io/nats-server/v2 v2.10.14
github.com/nats-io/nats.go v1.34.1
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.19.0
github.com/redis/go-redis/v9 v9.5.1
github.com/reugn/go-quartz v0.11.2
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/travisjeffery/go-dynaport v1.0.0
go.opentelemetry.io/otel v1.25.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.25.0
go.opentelemetry.io/otel/exporters/prometheus v0.47.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.25.0
go.opentelemetry.io/otel/metric v1.25.0
go.opentelemetry.io/otel/sdk v1.25.0
go.opentelemetry.io/otel/sdk/metric v1.25.0
go.opentelemetry.io/otel/trace v1.25.0
go.uber.org/atomic v1.11.0
go.uber.org/goleak v1.3.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/net v0.24.0
golang.org/x/sync v0.7.0
google.golang.org/protobuf v1.33.0
k8s.io/api v0.29.4
k8s.io/apimachinery v0.29.4
k8s.io/client-go v0.29.4
k8s.io/utils v0.0.0-20240423183400-0849a56e8f22@0849a56e8f22
Earthfile
tochemey/docker-go 1.21.0-1.0.0
.github/workflows/build.yml
earthly/earthly v0.8.9
.github/workflows/pr.yml
earthly/earthly v0.8.9
This feature will allow from within the receiving handler to send batch messages to remote actors.
The first iteration of the implementation will focus on implementing a PoolRouter
that will send a specific type of message to a bunch of routees to process in parallel. There will be two types of routees:
Router features:
At the moment, actors created in cluster mode can be passivated on the node they are created. The passivated actor is removed from the actors map on the node it has been created. However, that information is not sent across the cluster which means that actor still has a reference in the cluster and that can cause an issue.
The cluster feature will help actor system nodes to form a cluster when that flag is turn on.
// Discovery helps discover other running actor system in a cloud environment
type Discovery interface {
// Start the discovery engine
Start(ctx context.Context, meta Meta) error
// Nodes returns the list of Nodes at a given time
Nodes(ctx context.Context) ([]*Node, error)
// Watch returns event based upon node lifecycle
Watch(ctx context.Context) (<-chan Event, error)
// EarliestNode returns the earliest node
EarliestNode(ctx context.Context) (*Node, error)
// Stop shutdown the discovery provider
Stop() error
}
With this interface we can implement mDNS, kubernetes and co discovery mode.
// Cluster defines the cluster contract
type Cluster interface {
// Start starts the cluster node
Start(ctx context.Context) error
// Stop stops the cluster node
Stop(ctx context.Context) error
// GetPeers fetches all the peers of a given node
GetPeers(ctx context.Context) ([]*Peer, error)
// PutActor adds an actor meta to the cluster
PutActor(ctx context.Context, actor *goaktpb.WireActor) error
// GetActor reads an actor meta from the cluster
GetActor(ctx context.Context, actorName string) (*goaktpb.WireActor, error)
}
Implement a raft node.
Each node on start will make use the discovery plugin to try and join an existing cluster using the underlying raft implementation.
This feature let an actor to stash some messages that it can process at later time. This will be an extension of the stash mechanism with a simple scheduler. The API definition will be as follow:
ScheduleOnce
: to schedule a message to be processed one timeScheduleTimes(count int)
: to schedule a message to be process count timesThis feature should be available both on the PID and the receiver context
This requires a better mailbox instead of the current buffered-based channel. Also, the receiving loop and behaviour stacks can be improved to enhance the performance.
Make tracing configurable
Add span tracing to the following methods on PID and ActorSystem:
Record errors in the span
We need to provide a event stream to publish events persisted on the event store so that downstream applications can subscribe to those events and build some read models.
Messages that cannot be delivered or handled will push to a deadletter box. The purpose of this feature is help debugging when there is some inconsistency in messages processing.
This feature will require:
The whole purpose of the event stream is to broadcast system events.
The current implementation uses the unary gRPC call for message processing. The downside is that message ordering is not guaranteed when there are lot of messages that are sent to the actor.
Switching to gRPC streaming will help guarantee message ordering.
This does not solve the issue of redeployment of actors on the dead node
NewDiscovery()
should accept typed configs type discoConfig struct
rather than using discovery.Config{}
.
disco := dnssd.NewDiscovery(dnssd.Config{
Domain: "xxx",
IPv6: false
})
This feature will help create a cluster of shards containing actors in a cluster.
RemoteSpawn method help start an actor on remote machine.
Register
the actor type with the actor systemRemoteSpawn
from the api or the actor PID.Add a method to remoting service to re-create an actor remotely with the following params:
message definition:
// Started is used when an actor has successfully started
message PostStart {
}
The current implementation does not allow the comparison of two PID and there is no proper way to get the ID
of an actor.
The current solution is to use the actor path.
TBD
Reading and merging env to configs should be handled by user using some modules like viper
or koanf
.
To my opinion, I always avoid using env and put all configs in local config files. I have come accross many times that a mysterious env is controlling a key feature and no one knows about it. It is a nightmare to debug.
Stashing enables an actor to temporarily buffer all or some messages that cannot or should not be handled using the actorβs current behavior.
A typical example when this is useful is if the actor has to load some initial state or initialize some resources before it can accept the first real message. Another example is when the actor is waiting for something to complete before processing the next message.
{"level":"info","ts":"2024-04-19T13:59:51+08:00","msg":"enabling clustering..."}
{"level":"info","ts":"2024-04-19T13:59:51+08:00","msg":"starting cluster engine..."}
{"level":"info","ts":"2024-04-19T13:59:51+08:00","msg":"Starting GoAkt cluster Node service on (DESKTOP-1T48526:9000)....π€"}
{"level":"info","ts":"2024-04-19T13:59:51+08:00","msg":"Olric 0.6.0-alpha.1 on linux/amd64 go1.22.2 => olric.go:319"}
{"level":"error","ts":"2024-04-19T13:59:51+08:00","msg":"Failed to run the routing table subsystem: mDNS domain is not provided => olric.go:347"}
{"level":"error","ts":"2024-04-19T13:59:51+08:00","msg":"failed to start the cluster Node=(thingcross-0).π₯: mDNS domain is not provided"}
{"level":"info","ts":"2024-04-19T13:59:51+08:00","msg":"127.0.1.1:9000 is gone => olric.go:448"}
goakt/internal/cluster/node.go
Lines 217 to 226 in 408564c
The context is never cancelled.
The current implementation is limited to very few scenarios of dead letters. We need to extend it to other parts of the message delivery system in the code to capture more data.
This change will not alter the API definition which means developers don't need to do anything.
This ticket/issue outlines the various metrics to implement for both the actor system and a given actor.
This is just an enhancement for the various unit tests added to simulate and demonstrate the various clustering scenario.
An actor can should be able to behave like a FSM. An FSM as described in the Erlang design principles is a set of relations of the form:
State(S) x Event(E) -> Actions (A), State(Sβ)
.
If we are in state S and the event E occurs, we should perform the actions A and make a transition to the state Sβ. So what it means that an actor in state S when a message is received will process the message with state. When it transits to another state, every new message will be processed with the new state behaviour. This type of feature helps make an actor wear many coats.
Let us consider for instance we are building an authentication/authorization system using Go-Akt
. The session actor can switch between the various states transitions:
Authenticating
-> Authenticated
-> Authorizing
-> Authorized
.
Yes of course this one way of building such system using a single actor.
This is to illustrate an idea #208
The issue is about the host node ip. Need to re-test it properly when cluster is enabled.
The cluster implementation simply relies on a distributed sharded key/value store engine. It handles the rebalance and the sharding mechanism.
It is an issue because that actor cannot be found when its node dies
Implementation details: Simple distributed in-memory key/value store
The current implementation does not allow the user to specify his/her partitioner function using a different algo. This can be an issue when the integration requires a different hash algo
BatchTell
- helps send a bunch of messages to a given actor to process in a fire-forget manner.BatchAsk
- helps send a bunch of messages to a given actor to process and expect responses. The responses will be sent in the same order as the messages.The messages will be processed one after the other in the order they are sent.
The current implementation comes bundled with Kubernetes as DSP. We need more DSPs for the cloud community. For instance:
Consul integration
mDNS integration
NATs integration
This is necessary because of:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.