### Virtual Actor Cluster Basics in Go Source: https://context7.com/asynkron/protoactor-website/llms.txt Demonstrates the fundamental setup for virtual actors in Go using Proto.Actor, including defining a cluster kind, configuring and starting a cluster member, and activating/messaging a grain. ```go // Go — virtual actor cluster basics import ( "github.com/asynkron/protoactor-go/cluster" "github.com/asynkron/protoactor-go/cluster/clusterproviders/consul" ) clusterKind := cluster.NewKind("user", actor.PropsFromProducer(func() actor.Actor { return &UserGrain{} })) c := cluster.New(system, cluster.Configure("my-cluster", consulProvider, identityLookup, clusterKind)) c.StartMember() // Activate (or find) a grain and send a message grain := c.Get("user-123", "user") grain.Tell(&SendMessageRequest{Text: "hello"}) ``` -------------------------------- ### Initialize and Start Proto.Remote Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-7/lesson-3/_index.md Configures serialization with message descriptors and starts the Proto.Remote instance on a specified host and port. ```csharp serialization.RegisterFileDescriptor(ChatReflection.Descriptor); var remote = new Remote(system, serialization); remote.Start("127.0.0.1", 8000); ``` -------------------------------- ### Configure and Start Proto.Cluster Member Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-go.md Set up and start a Proto.Cluster member. This includes configuring the Actor System, remote transport, and cluster provider. ```go package main import ( "fmt" "github.com/asynkron/protoactor-go/actor" "github.com/asynkron/protoactor-go/cluster" "github.com/asynkron/protoactor-go/cluster/clusterproviders/consul" "github.com/asynkron/protoactor-go/cluster/identitylookup/disthash" "github.com/asynkron/protoactor-go/remote" ) func main() { system := actor.NewActorSystem() provider, _ := consul.New() lookup := disthash.New() remoteConfig := remote.Configure("localhost", 0) clusterConfig := cluster.Configure("ProtoClusterTutorial", provider, lookup, remoteConfig) c := cluster.New(system, clusterConfig) c.StartMember() fmt.Println("Cluster member started. Press Enter to exit...") fmt.Scanln() c.Shutdown(true) } ``` -------------------------------- ### Install Proto.Actor Cluster Tutorial Helm Chart Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-kubernetes.md Use this Helm command to install the Proto.Actor cluster tutorial chart. Replace `proto-cluster-tutorial` with your desired release name and `chart-tutorial` with the path to your chart directory. ```sh helm install proto-cluster-tutorial chart-tutorial ``` -------------------------------- ### Setup Partition Identity Lookup Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/partition-idenity-lookup.md Configure the cluster with the PartitionIdentityLookup strategy. This is the default setup for the cluster. ```csharp actorSystem.WithCluster( ClusterConfig .Setup(clusterName, clusterProvider, new PartitionIdentityLookup()) ); ``` -------------------------------- ### Complete Actor System Example Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-2/lesson-5/_index.md A complete example demonstrating the creation of an actor system, defining actor props, and spawning an actor instance. Includes basic console output for tracking. ```csharp using System; using System.Threading.Tasks; using Proto; namespace MovieStreaming { public class PlaybackActor : IActor { public PlaybackActor() => Console.WriteLine("Creating a PlaybackActor"); public Task ReceiveAsync(IContext context) { return Task.CompletedTask; } } class Program { static void Main(string[] args) { var system = new ActorSystem(); Console.WriteLine("Actor system created"); var props = Props.FromProducer(() => new PlaybackActor()); var pid = system.Root.Spawn(props); Console.ReadLine(); } } } ``` -------------------------------- ### Install Proto.Actor Go Packages Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-go.md Install the necessary Proto.Actor Go packages for your project. This command fetches the latest stable versions. ```bash go get github.com/asynkron/protoactor-go@latest ``` -------------------------------- ### Install Proto.Remote NuGet Packages Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/remote.md Install the necessary Proto.Remote and Proto.Remote.GrpcNet packages via the Package Manager Console in Visual Studio. ```powershell Install-Package Proto.Remote Install-Package Proto.Remote.GrpcNet ``` -------------------------------- ### Start Go Remote Server Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp2025/chapter-3/configuration.md Initializes and starts the remote server in Go using the configured actor system and remote settings. ```go remoter := remote.NewRemote(system, config) remoter.Start() ``` -------------------------------- ### Start Cluster Client Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/using-cluster-net.md Asynchronously start the current process as a client, allowing it to send messages to the cluster without being a full member. ```csharp await _actorSystem .Cluster() .StartClientAsync(); ``` -------------------------------- ### Go Proto.Remote Configuration and Startup Source: https://context7.com/asynkron/protoactor-website/llms.txt Configures and starts a Proto.Remote server in Go, specifying the host and port for binding. ```go // Go — configure and start remote import ( "github.com/asynkron/protoactor-go/actor" "github.com/asynkron/protoactor-go/remote" ) cfg := remote.Configure("0.0.0.0", 8080) r := remote.NewRemote(actor.NewActorSystem(), cfg) r.Start() ``` -------------------------------- ### Initialize Actor System (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/chatexample/_index.md Initializes and starts the ProtoActor system with remote capabilities, configuring it to bind to localhost on port 8000. ```go system := actor.NewActorSystem() config := remote.Configure("127.0.0.1", 8000) remoter := remote.NewRemote(system, config) remoter.Start() context := system.Root ``` -------------------------------- ### Install Protobuf Plugin for Proto.Actor Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/clusterintro/_index.md Install the protoc-gen-gograinv2 plugin for Proto.Actor. Ensure you specify the @dev branch. ```bash go get github.com/AsynkronIT/protoactor-go/protobuf/protoc-gen-gograinv2@dev ``` -------------------------------- ### Ponger Implementation Example Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/clusterintro/_index.md Example implementation of the Ponger interface, demonstrating how to handle initialization, termination, default messages, and the Ping method. ```APIDOC ## Ponger Implementation This section provides an example implementation of the `ponger` struct, fulfilling the `Ponger` interface requirements. ```go type ponger struct { cluster.Grain } var _ messages.Ponger = (*ponger)(nil) // This guarantees ponger implements messages.Ponger. func (*ponger) Terminate() { // A virtual actor always exists, so this usually does not terminate once the actor is initialized. // However, a timeout can be set so a virtual actor terminates itself when no message comes for a certain period of time. // Do the finalization if required. } func (*ponger) ReceiveDefault(ctx actor.Context) { // Do something with a received message. Not necessarily in request-response manner. } func (*ponger) Ping(ping *messages.PingMessage, ctx cluster.GrainContext) (*messages.PongMessage, error) { // Receive ping and return pong in gRPC-based protocol return nil, nil } ``` Method implementations could be somewhat like below. Because the actor struct is already generated and exported to protos_protoactor.go by protoc-ge-gograinv2, the implementations are pretty simple. ```go // Terminate takes care of the finalization. func (p *ponger) Terminate() { // Do finalization if required. e.g. Store the current state to storage and switch its behavior to reject further messages. // This method is called when a pre-configured idle interval passes from the last message reception. // The actor will be re-initialized when a message comes for the next time. // Terminating the idle actor is effective to free unused server resource. // // A poison pill message is enqueued right after this method execution and the actor eventually stops. log.Printf("Terminating ponger: %s", p.ID()) } // ReceiveDefault is a default method to receive and handle incoming messages. func (*ponger) ReceiveDefault(ctx actor.Context) { switch msg := ctx.Message().(type) { case *messages.PingMessage: pong := &messages.PongMessage{Cnt: msg.Cnt} log.Print("Received ping message") ctx.Respond(pong) default: // Do nothing } } // Ping is a method to support gRPC Ponger service. func (*ponger) Ping(ping *messages.PingMessage, ctx cluster.GrainContext) (*messages.PongMessage, error) { // The sender process is not a sending actor, but a future process log.Printf("Sender: %+v", ctx.Sender()) pong := &messages.PongMessage{ Cnt: ping.Cnt, } return pong, nil } ``` ``` -------------------------------- ### Run Pinger Actor for Proto.Actor Cluster Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/clusterintro/_index.md This example demonstrates how to set up a Proto.Actor cluster client that periodically sends ping messages to a remote 'Ponger' grain. It configures the actor system, remote environment, and cluster, then starts a ping actor that sends messages until an interrupt signal is received. ```go package main import ( "github.com/AsynkronIT/protoactor-go/actor" "github.com/AsynkronIT/protoactor-go/cluster" "github.com/AsynkronIT/protoactor-go/cluster/automanaged" "github.com/AsynkronIT/protoactor-go/remote" "log" "os" "os/signal" "protoactor-go-sender-example/cluster/messages" time ) var cnt uint64 = 0 type pingActor struct { cluster *cluster.Cluster cnt uint } func (p *pingActor) Receive(ctx actor.Context) { switch ctx.Message().(type) { case struct{}: cnt += 1 ping := &messages.PingMessage{ Cnt: cnt, } client := messages.GetPongerGrainClient(p.cluster, "ponger-1") option := cluster.NewGrainCallOptions(p.cluster).WithRetry(3) pong, err := client.Ping(ping, option) if err != nil { log.Print(err.Error()) return } log.Printf("Received %v", pong) case *messages.PongMessage: // Never comes here. // When the pong grain responds to the sender's gRPC call, // the sender is not a ping actor but a future process. log.Print("Received pong message") } } func main() { // Setup actor system system := actor.NewActorSystem() // Prepare remote env that listens to 8081 remoteConfig := remote.Configure("127.0.0.1", 8081) // Configure cluster on top of the above remote env // This member uses port 6330 for cluster provider, and add ponger member -- localhost:6331 -- as member. // With automanaged implementation, one must list up all known members at first place to ping each other. // Note that this member itself is not registered as a member member because this only works as a client. cp := automanaged.NewWithConfig(1*time.Second, 6330, "localhost:6331") clusterConfig := cluster.Configure("cluster-example", cp, remoteConfig) c := cluster.New(system, clusterConfig) // Start as a client, not as a cluster member. c.StartClient() // Start ping actor that periodically send "ping" payload to "Ponger" cluster grain pingProps := actor.PropsFromProducer(func() actor.Actor { return &pingActor{ cluster: c, } }) pingPid := system.Root.Spawn(pingProps) // Subscribe to signal to finish interaction finish := make(chan os.Signal, 1) signal.Notify(finish, os.Interrupt, os.Kill) // Periodically send ping payload till signal comes ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for { select { case <-ticker.C: system.Root.Send(pingPid, struct{}{}) case <-finish: log.Print("Finish") return } } } ``` -------------------------------- ### Install Proto.Actor Simulator Helm Chart with Custom Values Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-kubernetes.md Deploy the simulator to your Kubernetes cluster using Helm. This command installs the `chart-tutorial` chart, overriding default configurations with settings from `simulator-values.yaml`. ```sh helm install simulator chart-tutorial --values .\simulator-values.yaml ``` -------------------------------- ### Using Touch and Touched Messages for Liveness Check Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/messages/touch.md This example shows how to send a `Touch` message to an actor and verify the `Touched` response to confirm the actor's liveness. Ensure the Proto.Actor library is installed. ```csharp using System; using Proto; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var props = Props.FromProducer(() => new MyActor()); var actorSystem = new ActorSystem(); var rootContext = actorSystem.Root; var pid = rootContext.Spawn(props); // Send a Touch message to check liveness var response = await rootContext.RequestAsync(pid, new Touch()); // Check the response if (response != null) { Console.WriteLine("Actor is alive"); } else { Console.WriteLine("Actor did not respond"); } // Keep the application running to observe the output Console.ReadLine(); } } class MyActor : IActor { public Task ReceiveAsync(IContext context) { if (context.Message is string message) { Console.WriteLine(message); } return Task.CompletedTask; } } ``` -------------------------------- ### Install Proto.Actor Package (.NET) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/getting-started.md Use the NuGet package manager to install the Proto.Actor library in your .NET project. ```powershell PM> Install-Package Proto.Actor ``` -------------------------------- ### Serilog Configuration for Proto.Actor Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/logging.md Example appsettings.json for Serilog, demonstrating how to configure log levels, sinks (Console, Seq), and enrichment for Proto.Actor. ```json "Serilog": { "Using": [ "Serilog.Exceptions", "Serilog", "Serilog.Sinks.Console", "Serilog.Sinks.Seq" ], "MinimumLevel": { "Default": "Information", "Override": { "System": "Information", "Microsoft": "Warning", "Microsoft.AspNetCore": "Warning", "System.Net.Http.HttpClient": "Warning", //set log level for proto.actor cluster "Proto.Cluster": "Warning", } }, "WriteTo": [ { "Name": "Console", "Args": { "restrictedToMinimumLevel": "Debug", "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Environment} {ApplicationName} {ApplicationVersion} {ServiceId} {ChargePointId}: {Message} {Exception} {NewLine}" } }, { "Name": "Seq", "Args": { "serverUrl": "http://localhost:5341" } } ], "Enrich": [ "FromLogContext", "WithExceptionDetails" ] }, //other configs ``` -------------------------------- ### Example of Generated File Path Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/codegen-net.md This is an example of the file path where generated grain code will be located after building the project. ```txt MyProject\obj\Debug\net6.0\protopotato\CounterGrain-9DAD25B670A612931CE9F63A07C26BDF.cs ``` -------------------------------- ### Start HelloWorld Actor (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/hello-world.md Configures and spawns a new instance of the HelloWorldActor using Proto.Actor in Go. Props define the actor's behavior. ```go props := actor.PropsFromProducer(func() actor.Actor { return &HelloWorldActor{} }) pid := system.Root.Spawn(props) ``` -------------------------------- ### Transitioning to Persistence in Starting Method Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/money-transfer-saga/_index.md Modify the Starting method to persist a 'TransferStarted' event instead of directly changing behavior. This ensures state changes are logged for recovery. ```csharp private async Task Starting(IContext context) { if (context.Message is Started) { context.SpawnNamed(TryDebit(_from, -_amount), "DebitAttempt"); await _persistence.PersistEventAsync(new TransferStarted()); } } ``` -------------------------------- ### Start Second Cluster Member and Configure First Member Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-net.md Starts the second member of the Proto.Actor cluster on a different URL and configures the first member with a remote port and simulation settings. ```bash dotnet run --no-build --urls "http://localhost:5162" dotnet run --no-build --urls "http://localhost:5161" ProtoRemotePort=5000 RunSimulation=false ``` -------------------------------- ### Example: Using Watch and Unwatch Messages in C# Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/messages/watch.md This C# example demonstrates how to use `context.Watch` to monitor an actor's lifecycle and how to handle `Terminated` messages. It also shows the conceptual use of `context.Unwatch`. ```csharp using System; using Proto; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var actorSystem = new ActorSystem(); var rootContext = actorSystem.Root; var props = Props.FromProducer(() => new MyActor()); var pid = rootContext.Spawn(props); var watcherProps = Props.FromProducer(() => new WatcherActor(pid)); var watcherPid = rootContext.Spawn(watcherProps); // Keep the application running to observe the output Console.ReadLine(); } } class MyActor : IActor { public Task ReceiveAsync(IContext context) { return Task.CompletedTask; } } class WatcherActor : IActor { private readonly PID _target; public WatcherActor(PID target) { _target = target; } public Task ReceiveAsync(IContext context) { switch (context.Message) { case Started _: // Start watching the target actor context.Watch(_target); Console.WriteLine($"Started watching {_target}"); break; case Terminated msg when msg.Who.Equals(_target): // Handle the termination of the target actor Console.WriteLine($"Actor {_target} has terminated"); break; } return Task.CompletedTask; } } ``` -------------------------------- ### Registering a Service with Microsoft.Extensions.DependencyInjection Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/di.md Register a service implementation with its interface in the DI container. Ensure the concrete class 'Example' is defined in your project. ```csharp public void ConfigureServices (IServiceCollection services) { services.Add (new ExampleService (IExample, new Example ())); } ``` -------------------------------- ### Enable Prometheus Metrics in Go Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp2025/chapter-2/metrics.md Start Prometheus collectors for Proto.Actor metrics in Go. Ensure the necessary Prometheus metrics package is imported. ```go package main import ( "github.com/asynkron/protoactor-go/actor" prom "github.com/asynkron/protoactor-go/metrics/prometheus" ) func main() { system := actor.NewActorSystem() prom.StartCollectors(system) // start Prometheus collectors pid := system.Root.Spawn(actor.PropsFromProducer(func() actor.Actor { return &myActor{} })) _ = pid } ``` -------------------------------- ### Registering Services for DI Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/codegen-net.md Register your services with the .NET dependency injection container. This example shows registering a Slack notification sender. ```csharp services.AddSingleton(); ``` -------------------------------- ### Implement the Generated GrainBase Class Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/codegen-net.md Implement the abstract CounterGrainBase class to define the grain's behavior. This example shows incrementing and getting a counter value. ```csharp using Proto; using Proto.Cluster; namespace MyProject; public class CounterGrain : CounterGrainBase { private int _value = 0; public CounterGrain(IContext context) : base(context) { } public override Task Increment() { _value++; return Task.CompletedTask; } public override Task GetCurrentValue() { return Task.FromResult(new CounterValue { Value = _value }); } } ``` -------------------------------- ### Collect Allocations and Get Snapshot with dotMemory Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/performance/dotnetos.md Use dotMemory profiling API to collect and snapshot memory allocations. Call `CollectAllocations(true)` at the start and `GetSnapshot` before and after the code section to analyze. ```csharp MemoryProfiler.CollectAllocations(true); MemoryProfiler.GetSnapshot($ ``` ```csharp MemoryProfiler.GetSnapshot($ ``` -------------------------------- ### Initialize Go Module and Add Dependency Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/getting-started.md Set up a new Go module and fetch the Proto.Actor dependency using go mod and go get. ```bash go mod init greeter go get github.com/asynkron/protoactor-go ``` -------------------------------- ### Configure Kubernetes Provider Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/kubernetes-provider-net.md Configures the Proto.Actor remote settings and Kubernetes cluster provider. Ensure the 'Proto.Cluster.Kubernetes' NuGet package is installed. This setup is crucial for deploying Proto.Actor applications within a Kubernetes cluster. ```csharp (GrpcCoreRemoteConfig, IClusterProvider) ConfigureForKubernetes(IConfiguration config) { var kubernetes = new Kubernetes(KubernetesClientConfiguration.InClusterConfig()); var clusterProvider = new KubernetesProvider(kubernetes); var remoteConfig = GrpcNetRemoteConfig .BindToAllInterfaces(advertisedHost: config["ProtoActor:AdvertisedHost"]) .WithProtoMessages(EmptyReflection.Descriptor) .WithProtoMessages(MessagesReflection.Descriptor) .WithLogLevelForDeserializationErrors(LogLevel.Critical) .WithRemoteDiagnostics(true); return (remoteConfig, clusterProvider); } ``` -------------------------------- ### PlaybackActor Handling Started and PlayMovieMessage Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-3/lesson-2/_index.md Extends the 'PlaybackActor' to handle both 'Started' system messages and custom 'PlayMovieMessage'. The 'Started' message is processed first, allowing for initialization before custom message handling. ```csharp public class PlaybackActor : IActor { public PlaybackActor() => Console.WriteLine("Creating a PlaybackActor"); public Task ReceiveAsync(IContext context) { switch (context.Message) { case Started msg: ProcessStartedMessage(msg); break; case PlayMovieMessage msg: ProcessPlayMovieMessage(msg); break; } return Task.CompletedTask; } } ``` -------------------------------- ### Run Actor System (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/getting-started.md Initialize an actor.ActorSystem, define actor properties, spawn a greetingActor, and send it a *Greet message. Includes code to prevent immediate program exit. ```go func main() { system := actor.NewActorSystem() props := actor.PropsFromProducer(func() actor.Actor { return &greetingActor{} }) pid := system.Root.Spawn(props) // Send a message to the actor system.Root.Send(pid, &Greet{Who: "World"}) // Prevent the program from exiting immediately _, _ = console.ReadLine() } ``` -------------------------------- ### Start Cluster Member Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/using-cluster-net.md Asynchronously start the current process as a member of the cluster. ```csharp await _actorSystem .Cluster() .StartMemberAsync(); ``` -------------------------------- ### Handle `Started` Message in C# Actor Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/messages/started.md Demonstrates how to handle the `Started` system message within an actor by checking the message type in the `ReceiveAsync` method. This is useful for executing initialization logic when an actor first starts. ```csharp using Proto; using System; public class MyActor : IActor { public Task ReceiveAsync(IContext context) { switch (context.Message) { case Started _: Console.WriteLine("Actor started"); break; } return Task.CompletedTask; } } ``` -------------------------------- ### Initialize Actor System with Persistence Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-9/lesson-2/_index.md Sets up a new Proto.Actor system and its root context. This is the entry point for creating and managing actors within the system. ```csharp static void Main(string[] args) { var system = new ActorSystem(); var context = new RootContext(system); ``` -------------------------------- ### Start HelloWorld Actor (.NET) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/hello-world.md Configures and spawns a new instance of the HelloWorldActor using Proto.Actor in .NET. Props define the actor's behavior. ```csharp using Proto; var props = Props.FromProducer(() => new HelloWorldActor()); var pid = system.Root.Spawn(props); ``` -------------------------------- ### C# Client Application Setup Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-7/lesson-3/_index.md Initializes the actor system, remote connection, and defines the client's message handling logic. This code sets up the client to receive and display messages from the server. ```csharp class Program { static void Main(string[] args) { var system = new ActorSystem(); var serialization = new Serialization(); serialization.RegisterFileDescriptor(ChatReflection.Descriptor); var remote = new Remote(system, serialization); remote.Start("127.0.0.1", 0); var server = new PID("127.0.0.1:8000", "chatserver"); var context = new RootContext(system, default, openTracingMiddleware); var props = Props.FromFunc(ctx => { switch (ctx.Message) { case Connected connected: Console.WriteLine(connected.Message); break; case SayResponse sayResponse: Console.WriteLine($"{sayResponse.UserName} {sayResponse.Message}"); break; case NickResponse nickResponse: Console.WriteLine($"{nickResponse.OldUserName} is now {nickResponse.NewUserName}"); break; } return Task.CompletedTask; }); var client = context.Spawn(props); context.Send(server, new Connect { Sender = client }); var nick = "Alex"; while (true) { var text = Console.ReadLine(); if (text.Equals("/exit")) { return; } if (text.StartsWith("/nick ")) { var t = text.Split(' ')[1]; context.Send(server, new NickRequest { OldUserName = nick, NewUserName = t }); nick = t; } else { context.Send(server, new SayRequest { UserName = nick, Message = text }); } } } } ``` -------------------------------- ### Run Actor System (.NET) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/getting-started.md Create an ActorSystem, define actor properties, spawn a GreetingActor, and send it a Greet message. Includes code to prevent immediate application exit. ```csharp var system = new ActorSystem(); var props = Props.FromProducer(() => new GreetingActor()); var pid = system.Root.Spawn(props); // Send a message to the actor system.Root.Send(pid, new Greet("World")); // Prevent the application from exiting immediately Console.ReadLine(); ``` -------------------------------- ### ProcessStartedMessage Implementation Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-3/lesson-2/_index.md Implements the handler for the 'Started' system message within the 'PlaybackActor'. It logs a green message to the console indicating the actor has successfully started. ```csharp private void ProcessStartedMessage(Started msg) { ColorConsole.WriteLineGreen("PlaybackActor Started"); } ``` -------------------------------- ### Base ASP.NET Core Web App Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-net.md Sets up a minimal ASP.NET Core Web Application with a basic "Hello, Proto.Cluster!" endpoint. This serves as the foundation for the Proto.Cluster tutorial. ```csharp var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("", () => Task.FromResult("Hello, Proto.Cluster!")); app.Run(); ``` -------------------------------- ### Start and Shutdown Cluster Member Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-net.md Explicitly start and shut down a cluster member. The `StartMemberAsync` method initiates the member's participation in the cluster, while `ShutdownAsync` gracefully removes it. ```csharp await _actorSystem .Cluster() .StartMemberAsync(); await _actorSystem .Cluster() .ShutdownAsync(); ``` -------------------------------- ### C# Proto.Remote Server Configuration and Startup Source: https://context7.com/asynkron/protoactor-website/llms.txt Configures and starts a Proto.Remote server in C#, binding to a specific address and port, and registering actor kinds. Supports gRPC compression. ```csharp // .NET — server: configure and start remote using Proto.Remote; using Proto.Remote.GrpcNet; var remoteConfig = GrpcNetRemoteConfig .BindTo("0.0.0.0", 12000) .WithProtoMessages(MyMessagesReflection.Descriptor) .WithRemoteKind("echo", Props.FromProducer(() => new EchoActor())); var system = new ActorSystem() .WithRemote(remoteConfig); await system.Remote().StartMemberAsync(); ``` ```csharp // With gRPC compression var compressedConfig = GrpcNetRemoteConfig .BindTo("0.0.0.0", 12000) .WithProtoMessages(ProtosReflection.Descriptor) .WithChannelOptions(new GrpcChannelOptions { CompressionProviders = new[] { new GzipCompressionProvider(CompressionLevel.Fastest) } }); ``` -------------------------------- ### Mermaid Graph Diagram Example Source: https://github.com/asynkron/protoactor-website/blob/master/AGENTS.md Example of a Mermaid graph diagram demonstrating actor, PID, and message styling with a green sender, light-blue PID, and message class. ```mermaid graph LR sender(Main) class sender green pid(PID) class pid light-blue msg(Hello) class msg message receiver((HelloWorld
Actor)) sender --> msg msg --- pid --> receiver ``` -------------------------------- ### Dockerfile for SmartBulbSimulatorApp Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-kubernetes.md This Dockerfile outlines the build process for the SmartBulbSimulatorApp, including restoring dependencies for both the simulator and the tutorial project, and publishing the simulator application. ```docker # Stage 1 - Build FROM mcr.microsoft.com/dotnet/sdk:6.0 AS builder WORKDIR /app/src # Restore COPY /ProtoClusterTutorial/*.csproj ./ProtoClusterTutorial/ COPY /SmartBulbSimulatorApp/*.csproj ./SmartBulbSimulatorApp/ RUN dotnet restore ./SmartBulbSimulatorApp/SmartBulbSimulatorApp.csproj -r linux-x64 # Build COPY . . RUN dotnet publish ./SmartBulbSimulatorApp/SmartBulbSimulatorApp.csproj -c Release -o /app/publish -r linux-x64 --no-self-contained --no-restore ``` -------------------------------- ### Start First Cluster Member Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-net.md Starts the first member of the Proto.Actor cluster. This command binds the application to a specific URL and assumes it's run from the ProtoClusterTutoral project directory. ```sh dotnet run --no-build --urls "http://localhost:5161" ``` -------------------------------- ### Create a Throttle Instance Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/throttle.md Configure the Throttle with the maximum number of events, the time duration, and a callback for when the throttle reopens. This setup prevents excessive logging during event floods. ```csharp private readonly ShouldThrottle _shouldThrottle; /* ... */ _shouldThrottle = Throttle.Create( // max number of events/calls 10, // in this duration TimeSpan.FromSeconds(5), // callback for when valve opens back up again count => _logger.LogInformation("Throttled {LogCount} logs for component xyz", count) ); ``` -------------------------------- ### Get Grain Client Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/codegen-net.md Obtain a grain client using the Get extension method on Cluster or IContext. Use this client to send messages to a specific grain identity. ```csharp CounterGrainClient client = cluster.GetCounterGrain("click-counter"); // or CounterGrainClient client = context.GetCounterGrain("click-counter"); ``` -------------------------------- ### Create Actor System (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/hello-world.md Initializes a new Proto.Actor system in Go. This system acts as a container and manager for actors. ```go import ( "github.com/asynkron/protoactor-go/actor" ) system := actor.NewActorSystem() ``` -------------------------------- ### Create ActorSystem Runtime Container (Go) Source: https://context7.com/asynkron/protoactor-website/llms.txt Initialize the ActorSystem in Go to manage actor lifecycles and spawn top-level actors. Messages are sent using the root context. ```go import "github.com/asynkron/protoactor-go/actor" system := actor.NewActorSystem() props := actor.PropsFromProducer(func() actor.Actor { return &MyActor{} }) pid := system.Root.Spawn(props) system.Root.Send(pid, &MyMessage{Text: "hello"}) system.Root.Stop(pid) ``` -------------------------------- ### Spawn and Use Actor in Go Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp2025/chapter-2/_index.md Illustrates creating an ActorSystem, defining actor Props, spawning an actor, and sending a message to it using its PID. This is the standard way to initiate actor communication in Go with Proto.Actor. ```go import ( "github.com/asynkron/protoactor-go/actor" "time" ) func main() { system := actor.NewActorSystem() // new ActorSystem props := actor.PropsFromProducer(func() actor.Actor { return &greetingActor{} }) pid := system.Root.Spawn(props) // spawn the actor // Send a message to the actor system.Root.Send(pid, &Greet{Who: "World"}) // Prevent the program from exiting immediately (to allow actor to process message) time.Sleep(500 * time.Millisecond) } ``` -------------------------------- ### Writing an Integration Test Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/integration-tests.md Set up an integration test class using the custom test fixture. This example shows how to inject services and dependencies required for the test. ```csharp public class SomeTest : IClassFixture> { private readonly ITestOutputHelper _output; private readonly Cluster _cluster; private readonly MockStore _store; public SomeTest(MysystemClassFixture factory, ITestOutputHelper output) { var services = factory.Server.Services; _output = output; _cluster = services.GetRequiredService(); _store = (MockStore)services.GetRequiredService>(); } ... ``` -------------------------------- ### Configure Actor System with Supervision Strategy Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-3/lesson-2/_index.md Sets up the Actor System and spawns the PlaybackActor with a OneForOneStrategy. This strategy dictates how to handle child actor failures, in this case, by restarting the failed child. ```csharp var system = new ActorSystem(); Console.WriteLine("Actor system created"); var props = Props.FromProducer(() => new PlaybackActor()).WithChildSupervisorStrategy(new OneForOneStrategy(Decider.Decide, 1, null)); var pid = system.Root.Spawn(props); system.Root.Send(pid, new PlayMovieMessage("The Movie", 44)); system.Root.Send(pid, new PlayMovieMessage("The Movie 2", 54)); system.Root.Send(pid, new PlayMovieMessage("The Movie 3", 64)); system.Root.Send(pid, new PlayMovieMessage("The Movie 4", 74)); Thread.Sleep(50); Console.WriteLine("press any key to restart actor"); Console.ReadLine(); system.Root.Send(pid, new Recoverable()); Console.ReadLine(); ``` -------------------------------- ### Implement Cluster Member Hosted Service Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/cluster/getting-started-net.md A hosted service for managing the Proto.Cluster member lifecycle within an ASP.NET Core application. It ensures the cluster member starts when the application starts and shuts down gracefully when the application stops. ```csharp using Proto; using Proto.Cluster; namespace ProtoClusterTutorial; public class ActorSystemClusterHostedService : IHostedService { private readonly ActorSystem _actorSystem; public ActorSystemClusterHostedService(ActorSystem actorSystem) { _actorSystem = actorSystem; } public async Task StartAsync(CancellationToken cancellationToken) { Console.WriteLine("Starting a cluster member"); await _actorSystem .Cluster() .StartMemberAsync(); } public async Task StopAsync(CancellationToken cancellationToken) { Console.WriteLine("Shutting down a cluster member"); await _actorSystem .Cluster() .ShutdownAsync(); } } ``` -------------------------------- ### Connect to Server (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/chatexample/_index.md Initiates a connection to the server by sending a Connect message containing the client's PID. This establishes a two-way communication channel. ```Go context.Send(server, &messages.Connect{Sender: client}) ``` -------------------------------- ### Configure TLS (Go) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/remote.md Secure Proto.Remote connections with TLS certificates in Go. Load server and client credentials and configure them in `remote.Configure`. ```go package main import ( "github.com/asynkron/protoactor-go/actor" remote "github.com/asynkron/protoactor-go/remote" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) func main() { serverCreds, _ := credentials.NewServerTLSFromFile("server.crt", "server.key") clientCreds, _ := credentials.NewClientTLSFromFile("server.crt", "") cfg := remote.Configure("127.0.0.1", 8080, remote.WithServerOptions(grpc.Creds(serverCreds)), remote.WithDialOptions(grpc.WithTransportCredentials(clientCreds)), ) remote.NewRemote(actor.NewActorSystem(), cfg).Start() } ``` -------------------------------- ### Get Ponger Grain Client and Make gRPC Request Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/clusterintro/_index.md Acquire a PongerGrainClient instance to initiate gRPC-like requests. This method retries to get the destination PID up to a pre-defined threshold. Use this for reliable communication where a response is expected. ```go // Setup cluster c := cluster.Configure(...) // Get `PID` of ponger grain grain := messages.GetPongerGrainClient(clustr, "ponger-1") // Build a PingMessage payload and make a gRPC request. ping := &messages.PingMessage{ Cnt: 1, } // Explicitly define the retrial count option := cluster.NewGrainCallOptions(c).WithRetry(3) // Make a request and receive a response pong, err := grain.Ping(ping, option) ``` -------------------------------- ### Subscribe to DeadLetterEvents Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-6/lesson-5/_index.md A concise example of subscribing to the EventStream to capture DeadLetterEvents. ```csharp system.EventStream.Subscribe(msg => Console.WriteLine($"Sender: {msg.Sender}, Pid: {msg.Pid}, Message: {msg.Message}")); ``` -------------------------------- ### Example Actor System with DeadLetter Handling Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/deadletter.md Demonstrates setting up an Actor System, spawning an actor, subscribing to DeadLetterEvents, and sending messages including a PoisonPill to trigger dead lettering. ```csharp static async Task Main(string[] args) { var system = new ActorSystem(); var props = Props.FromProducer(() => new Echo()); var pid = system.Root.Spawn(props); system.EventStream.Subscribe(msg => Console.WriteLine($"Sender: {msg.Sender}, Pid: {msg.Pid}, Message: {msg.Message}")); system.Root.Send(pid, new TestMessage()); await system.Root.PoisonAsync(pid); system.Root.Send(pid, new TestMessage()); Console.ReadLine(); } ``` -------------------------------- ### Initialize Actor System (.NET) Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/chatexample/_index.md Initializes and starts the ProtoActor system with remote capabilities, binding to localhost on port 8000 and configuring Protobuf message handling. ```csharp var config = BindToLocalhost(8000) .WithProtoMessages(ChatReflection.Descriptor); var system = new ActorSystem() .WithRemote(config); system .Remote() .StartAsync(); context = system.Root; ``` -------------------------------- ### Define IncrementPlayCountMessage Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-4/lesson-5/_index.md A message class to notify the MoviePlayCounterActor about a movie starting. It carries the title of the movie. ```csharp public class IncrementPlayCountMessage { public string MovieTitle { get; } public IncrementPlayCountMessage(string movieTitle) { MovieTitle = movieTitle; } } ``` -------------------------------- ### Create an Actor System Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/bootcamp/unit-2/lesson-5/_index.md Instantiate the ActorSystem class to create the environment where actors will run. It's generally recommended to have a single instance per application. ```csharp var system = new ActorSystem(); ``` -------------------------------- ### Starting Debit Attempt Source: https://github.com/asynkron/protoactor-website/blob/master/hugo/content/docs/money-transfer-saga/_index.md Initiates the debit attempt by spawning a dedicated actor and transitions the state to AwaitingDebitConfirmation. ```csharp private async Task Starting(IContext context) { if (context.Message is Started) { context.SpawnNamed(TryDebit(_from, -_amount), "DebitAttempt"); _behavior.Become(AwaitingDebitConfirmation); } } private Props TryDebit(PID targetActor, decimal amount) => Props .FromProducer(() => new AccountProxy(targetActor, sender => new Debit(amount, sender))); ```