### Start Application Remotely (Go) Source: https://docs.ergo.services/networking/remote-start-application Initiate the startup of an application on a remote node using the ApplicationStart methods provided by the gen.RemoteNode interface. Supports temporary, transient, and permanent startup modes, each accepting the application name and startup options. The parent of a remotely started application is set to the initiating node. ```go ApplicationStartTemporary(name gen.Atom, options gen.ApplicationOptions) error ApplicationStartTransient(name gen.Atom, options gen.ApplicationOptions) error ApplicationStartPermanent(name gen.Atom, options gen.ApplicationOptions) error ``` -------------------------------- ### Control Remote Application Start Access (Go) Source: https://docs.ergo.services/networking/remote-start-application Manage which remote nodes can start specific applications using EnableApplicationStart and DisableApplicationStart. These methods take an application name and a list of permitted nodes. If no nodes are specified for DisableApplicationStart, all remote nodes are permitted. Calling DisableApplicationStart without nodes fully disables remote starting. ```go EnableApplicationStart(name gen.Atom, nodes ...gen.Atom) error DisableApplicationStart(name gen.Atom, nodes ...gen.Atom) error ``` -------------------------------- ### Ergo Framework: Example Meta-Process for Network Data Handling (Go) Source: https://docs.ergo.services/basics/meta-process An example implementation of a custom meta-process in Ergo Framework using Go. This meta-process reads data from a network connection and forwards it to its parent process, also handling incoming messages by writing them back to the connection. It embeds gen.MetaProcess for access to framework methods. ```go createMyMeta(conn net.Conn) gen.MetaBehavior { return &myMeta{ conn: conn, } } type myMeta struct { gen.MetaProcess // Embedding the gen.MetaProcess interface conn net.Conn. // Network connection } func (mm *myMeta) Start(meta gen.MetaProcess) error { // Assign the meta-process instance to the embedded interface mm.MetaProcess = meta // Ensure that the socket is closed upon exit defer close(mm.conn) // Read data from the socket in a loop for { buf := make([]byte, 1024) n, err mm.conn.Read(buf) if err != nil { return err // Terminate the meta-process on error } // Send the data to the parent process mm.Send(mm.Parent(), buf[:n]) } return nil // meta-process terminated } func (mm *myMeta) HandleMessage(from gen.PID, message any) error { // Log information about the parent process mm.Log().Info("my parent process is %s", mm.Parent()) // Handle received messages as byte slice if data, ok := message.([]byte); ok { // Write the data back to the connection mm.conn.Write(data) return nil } // Log if the message is of an unknown type mm.Log().Info("got unknown message %#v", message) return nil } func (mm *myMeta) Terminate(reason error) { // Close the connection when the meta-process is terminated close(mm.conn) } ``` -------------------------------- ### act.Pool Initialization and Termination Example Source: https://docs.ergo.services/actors/pool Provides example implementations for the Init and Terminate methods within a custom pool that embeds act.Pool. These methods are used for setting up pool options and logging termination events. ```go func (p *myPool) Init(args...) (act.PoolOptions, error) { var options act.PoolOptions p.Log().Info("starting pool process with name", p.Name()) // ... configure pool options using the options variable ... return options, nil } func (p *myPool) Terminate(reason error) { p.Log().Info("pool process terminated with reason: %s", reason) } ``` -------------------------------- ### Start Meta-Process with SpawnMeta (Go) Source: https://docs.ergo.services/basics/meta-process Initiates a new meta-process using the `SpawnMeta` method from the `gen.Process` interface. This method takes a `gen.MetaBehavior` and `genMetaOptions` as input and returns a `gen.Alias` for the new process or an error if startup fails. The returned alias can be used for inter-process communication. ```Go SpawnMeta(behavior gen.MetaBehavior, options genMetaOptions) (gen.Alias, error) ``` -------------------------------- ### Implement Supervisor and Child Actor - Go Source: https://docs.ergo.services/actors/supervisor Provides a Go example demonstrating the implementation of both a supervisor (`MySupervisor`) and its child process (`MyActor`). It shows the `Init` method for the supervisor, defining child specifications, and the `Init` method for the child actor. ```go // // Child process implementation // func factoryMyActor() gen.ProcessBehavior { return &MyActor{} } type MyActor struct { act.Actor } func (a *MyActor) Init(args ...any) error { a.Log().Info("starting child process MyActor") return nil } // // gen.SupervisorBehavior implementation // func (s *MySupervisor) Init(args ...any) (act.SupervisorSpec, error) { s.Log().Info("initialize supervisor...") spec := act.SupervisorSpec{ Children: []act.SupervisorChildSpec{ act.SupervisorChildSpec{ Name: "myChild", Factory: factoryMyActor, }, } } return spec, nil } ``` -------------------------------- ### Go: Install Ergo Actor Testing Library Source: https://docs.ergo.services/testing/unit This snippet shows the command to install the Ergo actor testing library using Go's package manager. It's a prerequisite for using the testing functionalities. ```bash go get ergo.services/ergo/testing/unit ``` -------------------------------- ### Install Saturn CLI Tool Source: https://docs.ergo.services/tools/saturn Command to install the latest version of the Saturn command-line interface tool using Go modules. This command fetches and installs the Saturn binary, making it available in your system's PATH. ```bash go install ergo.tools/saturn@latest ``` -------------------------------- ### Start Ergo Node with Erlang Network Stack (Go) Source: https://docs.ergo.services/extra-library/network-protocols/erlang This Go code snippet demonstrates how to start an Ergo node and configure it to use the Erlang network stack by default. It involves setting network options such as the cookie and specifying the Erlang network components (Registrar, Handshake, Proto). ```go import ( "fmt" "ergo.services/ergo" "ergo.services/ergo/gen" "ergo.services/proto/erlang23/dist" "ergo.services/proto/erlang23/epmd" "ergo.services/proto/erlang23/handshake" ) func main() { var options gen.NodeOptions // set cookie options.Network.Cookie = "123" // set Erlang Network Stack for this node options.Network.Registrar = epmd.Create(epmd.Options{}) options.Network.Handshake = handshake.Create(handshake.Options{}) options.Network.Proto = dist.Create(dist.Options{}) // starting node node, err := ergo.StartNode(gen.Atom(OptionNodeName), options) if err != nil { fmt.Printf("Unable to start node '%s': %s\n", OptionNodeName, err) return } node.Wait() } ``` -------------------------------- ### Implement Ergo Application with Actors and Supervisors (Go) Source: https://docs.ergo.services/basics/application Example implementation of an Ergo Application that combines an actor (A1) and a supervisor (S1). It demonstrates how to define the application's name, group members, and factory functions for the processes. ```Go func createApp() gen.ApplicationBehavior { return &app{} } type app struct{} func (a *app) Load(node gen.Node, args ...any) (gen.ApplicationSpec, error) { return gen.ApplicationSpec{ Name: "my_app", Group: []gen.ApplicationMemberSpec{ { Name: "a1", // start with registered name Factory: factory_A1, }, { // omitted field Name. will be started with no name Factory: factory_S1, }, }, }, nil } func (a *app) Start(mode gen.ApplicationMode) {} // no need? keep it empty func (a *app) Terminate(reason error) {} ... myApp := createApp() appName, err := node.ApplicationLoad(myApp) ``` -------------------------------- ### Starting a Process with a Factory in Go Source: https://docs.ergo.services/basics/process Demonstrates how to define a process behavior and start it using a factory function with `gen.ProcessFactory`. This is essential for creating new processes within the Ergo Framework, typically by embedding a generic actor like `act.Actor` and providing a factory that returns a `gen.ProcessBehavior`. ```go package main import ( "github.com/ergo-dao/ergo/gen" "github.com/ergo-dao/ergo/act" ) // MyActor embeds the generic actor behavior. type MyActor struct { act.Actor // embed generic actor } // factoryMyActor is a factory function that returns a gen.ProcessBehavior. func factoryMyActor() gen.ProcessBehavior { return &MyActor{} } func main() { // Example usage (assuming 'node' is an initialized gen.Node) // node.Spawn(factoryMyActor, gen.ProcessOptions{}) } ``` -------------------------------- ### Example Log Output Format in Go Source: https://docs.ergo.services/basics/logging This example shows a potential log output format when specific options are enabled for the default logger. It includes the timestamp, log level, and source of the log message, illustrating the effects of `TimeFormat`, `IncludeBehavior`, and `IncludeName` settings. ```go func (a *MyActor) Init(args ...any) error { ... a.Log().Info("starting my actor") return nil } ... pid, err := node.SpawnRegister("example", factoryMyActor, gen.ProcessOptions{}) node.Log().Info("started MyActor with PID %s", pid) ... 2024-07-31 07:53:57 [info] <6EE4478D.0.1017> 'example' main.MyActor: starting my actor 2024-07-31 07:53:57 [info] 6EE4478D: started MyActor with PID <6EE4478D.0.1017> ``` -------------------------------- ### Run etcd Registrar Tests with Docker Compose Source: https://docs.ergo.services/extra-library/registrars/etcd-client Commands to manage the etcd registrar testing environment using Docker Compose. Includes starting etcd, running tests with coverage, and cleaning up. ```bash # Start etcd for testing make start-etcd # Run tests with coverage make test-coverage # Run integration tests only make test-integration # Clean up make clean ``` -------------------------------- ### Create and Use etcd Registrar in Ergo Source: https://docs.ergo.services/extra-library/registrars/etcd-client This Go code snippet demonstrates how to initialize the etcd registrar client within the Ergo Framework. It shows setting up etcd connection options and integrating the registrar into the node's network options before starting the Ergo node. ```go import ( "ergo.services/ergo" "ergo.services/ergo/gen" "ergo.services/registrar/etcd" ) func main() { var options gen.NodeOptions ... registrarOptions := etcd.Options{ Endpoints: []string{"localhost:2379"}, Cluster: "production", } options.Network.Registrar = etcd.Create(registrarOptions) ... node, err := ergo.StartNode("demo@localhost", options) ... } ``` -------------------------------- ### Get Application Information Source: https://docs.ergo.services/networking/remote-start-application Retrieve information and status about a specific application. ```APIDOC ## Get Application Information ### Description This method allows you to retrieve detailed information about an application, including its current status, running on a specific node. ### Method `ApplicationInfo(name gen.Atom) (gen.ApplicationInfo, error)` This method is accessed via the `gen.Node` interface. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - `name` (gen.Atom) - Required - The name of the application to query. ### Request Example ```go // Assuming 'currentNode' is an instance of gen.Node appInfo, err := currentNode.ApplicationInfo("my_app") if err != nil { // Handle error } // Access information like appInfo.State, appInfo.PID, etc. ``` ### Response #### Success Response (200) Returns an object containing application information. - **State** (gen.ApplicationState) - The current state of the application (e.g., running, stopped). - **PID** (int) - The process ID of the application if running. - **Parent** (gen.Atom) - The name of the node that initiated the application's startup. - **Node** (gen.Atom) - The name of the node where the application is running. #### Response Example ```json { "State": "running", "PID": 12345, "Parent": "initiating_node", "Node": "target_node" } ``` #### Error Response - **400 Bad Request**: If the application name is invalid. - **404 Not Found**: If the application is not found on the node. - **500 Internal Server Error**: If there is a system issue retrieving application information. ``` -------------------------------- ### Create and Spawn meta.WebServer in Go Source: https://docs.ergo.services/meta-processes/web Illustrates the creation and spawning of a meta.WebServer process. It involves defining server options like host, port, and handler, creating the web server meta-process, and spawning it. Error handling is included for creation and spawning failures. ```go type MyWeb struct { act.Actor } // Init invoked on a start this process. func (w *MyWeb) Init(args ...any) error { // create an HTTP request multiplexer mux := http.NewServeMux() // create and spawn your handler meta-processes // and add them to the mux // // see above ... // create and spawn web server meta-process serverOptions := meta.WebServerOptions{ Port: 9090, Host: "localhost", // use node's certificate if it was enabled there CertManager: w.Node().CertManager(), Handler: mux, } webserver, err := meta.CreateWebServer(serverOptions) if err != nil { w.Log().Error("unable to create Web server meta-process: %s", err) return err } webserverid, err := w.SpawnMeta(webserver, gen.MetaOptions{}) if err != nil { // invoke Terminate to close listening socket webserver.Terminate(err) } w.Log().Info("started Web server %s: use http[s]://%s:%d/", webserverid, serverOptions.Host, serverOptions.Port) return nil } ``` -------------------------------- ### Handle etcd Cluster Events in Go Source: https://docs.ergo.services/extra-library/registrars/etcd-client This Go code demonstrates how to subscribe to and handle various etcd cluster events within an actor. It retrieves the registrar, gets the event stream, and processes messages like node joins, application starts, and configuration updates. ```go package main import ( "github.com/ergo-cloud/ergo/act" "github.com/ergo-cloud/ergo/gen" "github.com/ergo-cloud/ergo/lib/etcd" ) type myActor struct { act.Actor } func (m *myActor) HandleMessage(from gen.PID, message any) error { reg, err := m.Node().Network().Registrar() if err != nil { m.Log().Error("unable to get Registrar interface: %s", err) return nil } ev, err := reg.Event() if err != nil { m.Log().Error("Registrar has no registered Event: %s", err) return nil } m.MonitorEvent(ev) return nil } func (m *myActor) HandleEvent(event gen.MessageEvent) error { switch msg := event.Message.(type) { case etcd.EventNodeJoined: m.Log().Info("Node %s joined cluster", msg.Name) case etcd.EventApplicationStarted: m.Log().Info("Application %s started on node %s", msg.Name, msg.Node) case etcd.EventConfigUpdate: m.Log().Info("Configuration %s updated", msg.Item) // Handle specific configuration changes if msg.Item == "ssl.enabled" { if enabled, ok := msg.Value.(bool); ok { m.Log().Info("SSL %s", map[bool]string{true: "enabled", false: "disabled"}[enabled]) } } } return nil } ``` -------------------------------- ### Access Control for Remote Application Start Source: https://docs.ergo.services/networking/remote-start-application Manage which remote nodes are allowed to start specific applications. ```APIDOC ## Enable/Disable Remote Application Start Access ### Description These methods control whether specific applications can be started from remote nodes and which nodes are permitted to do so. ### Methods - `EnableApplicationStart(name gen.Atom, nodes ...gen.Atom) error`: Allows specified remote nodes to start the application. If `nodes` is omitted, all remote nodes can start the application. - `DisableApplicationStart(name gen.Atom, nodes ...gen.Atom) error`: Removes specified remote nodes from the list of allowed starters. If `nodes` is omitted, all remote nodes are blocked from starting the application. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - `name` (gen.Atom) - Required - The name of the application. - `nodes` (*gen.Atom) - Optional - A variadic list of node names permitted to start the application. ### Request Example ```go // Example: Enable 'my_app' to be started by 'node1' and 'node2' err := network.EnableApplicationStart("my_app", "node1", "node2") // Example: Disable 'my_app' from being started by 'node3' err = network.DisableApplicationStart("my_app", "node3") // Example: Disable remote start for 'my_app' entirely err = network.DisableApplicationStart("my_app") ``` ### Response #### Success Response (200) Returns `nil` error upon successful registration or de-registration. #### Response Example ```json { "success": true } ``` #### Error Response - **400 Bad Request**: If application name is invalid or node names are not recognized. - **500 Internal Server Error**: If there is a network or system issue. ``` -------------------------------- ### Implement Ergo Actor Lifecycle Callbacks (Go) Source: https://docs.ergo.services/actors/actor This Go code demonstrates the implementation of key callback methods for an Ergo actor, including `Init` for setup, `HandleMessage` for asynchronous communication, and `Terminate` for cleanup. It shows how to use embedded `gen.Process` methods like `Log`, `PID`, `Send`, and `SendResponse`. ```go package main import ( "github.com/ergo-services/server/gen" "github.com/ergo-services/server/act" ) type MyActor struct { act.Actor i int } func (a *MyActor) Init(args ...any) error { // get the gen.Log interface using Log method of embedded gen.Process interface a.Log().Info("starting process %s", a.PID()) // initialize value a.i = 100 // sending message to itself with methods Send and PID of embedded gen.Process a.Send(a.PID(), "hello") return nil } func (a *MyActor) HandleMessage(from gen.PID, message any) error { a.Log().Info("got message from %s: %s", from, message) // handling message // ... return nil } func (a *MyActor) Terminate(reason error) { a.Log().Info("%s terminated with reason: %s", a.PID(), reason) } ``` -------------------------------- ### Configure Cron Jobs (Go) Source: https://docs.ergo.services/basics/cron Demonstrates how to configure cron jobs at node startup using `gen.NodeOptions.Cron`. Shows how to define a `CronJob` with a name, scheduling spec, time zone, action, and fallback process. The example sends a message to a local process at a specific time. ```go func main() { var options gen.NodeOptions // ... locationAsiaShanghai, _ := time.LoadLocation("Asia/Shanghai") options.Cron.Jobs = []gen.CronJob{ gen.CronJob{Name: "job1", Spec: "7 21 * * *", Action: gen.CreateCronActionMessage(gen.Atom("myweb1"), gen.MessagePriorityNormal), Location: locationAsiaShanghai, Fallback: gen.ProcessFallback{Enable: true, Name: "myweb2"}, }, } node, err := ergo.StartNode("cron@localhost", options) if err != nil { panic(err) } // ... } ``` -------------------------------- ### Start Application Remotely Source: https://docs.ergo.services/networking/remote-start-application Initiate the startup of an application on a remote node with specified options. ```APIDOC ## Start Application Remotely ### Description This endpoint allows you to start an application on a remote node. The application can be started in different modes, and its parent will be set to the node initiating the startup. ### Methods - `ApplicationStartTemporary(name gen.Atom, options gen.ApplicationOptions) error`: Starts the application temporarily. - `ApplicationStartTransient(name gen.Atom, options gen.ApplicationOptions) error`: Starts the application transiently. - `ApplicationStartPermanent(name gen.Atom, options gen.ApplicationOptions) error`: Starts the application permanently. These methods are accessed via the `gen.RemoteNode` interface. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - `name` (gen.Atom) - Required - The name of the application to start. - `options` (gen.ApplicationOptions) - Required - Options for starting the application, including startup mode. ### Request Example ```go // Assuming 'remoteNode' is an instance of gen.RemoteNode appOptions := gen.ApplicationOptions{ // Define application options here, e.g., environment variables, args } // Start application temporarily err := remoteNode.ApplicationStartTemporary("my_app", appOptions) // Start application transiently err = remoteNode.ApplicationStartTransient("my_app", appOptions) // Start application permanently err = remoteNode.ApplicationStartPermanent("my_app", appOptions) ``` ### Response #### Success Response (200) Returns `nil` error upon successful initiation of application startup. #### Response Example ```json { "status": "Application startup initiated successfully" } ``` #### Error Response - **400 Bad Request**: If application name is invalid or options are malformed. - **403 Forbidden**: If the initiating node is not authorized to start the application. - **404 Not Found**: If the application or remote node does not exist. - **500 Internal Server Error**: If there is a network or system issue during startup. ``` -------------------------------- ### Set Configuration Values using etcdctl Source: https://docs.ergo.services/extra-library/registrars/etcd-client This example shows how to use the `etcdctl` command-line tool to set configuration values in etcd. It covers different configuration types (integer, float, boolean, string) and demonstrates hierarchical key structures for node-specific, cluster-wide, and global defaults. ```bash # Node-specific integer configuration (stored as string, converted to int64) etcdctl put services/ergo/cluster/production/config/web1/database.port "int:5432" # Cluster-wide float configuration (stored as string, converted to float64) etcdctl put services/ergo/cluster/production/config/*/cache.ratio "float:0.75" # Boolean configuration (stored as string, converted to bool) etcdctl put services/ergo/cluster/production/config/*/debug.enabled "bool:true" etcdctl put services/ergo/cluster/production/config/web1/ssl.enabled "bool:false" # Application-specific configuration (visible to all nodes using wildcard format) etcdctl put services/ergo/cluster/production/config/*/myapp.cache.size "int:256" etcdctl put services/ergo/cluster/production/config/*/client.timeout "int:30" # Global string configuration (stored and returned as string) etcdctl put services/ergo/config/global/log.level "info" ``` -------------------------------- ### Saturn Configuration Example: Specific Cluster Settings Source: https://docs.ergo.services/tools/saturn Example `saturn.yaml` configuration for a specific cluster named 'mycluster'. It demonstrates setting global variables for this cluster and overriding them for a particular node within that cluster. ```yaml Clusters: Var1: 123 Cluster@mycluster: Var1: 321 node@host: 654 ``` -------------------------------- ### Create and Run External Program using meta.Port in Go Source: https://docs.ergo.services/meta-processes/port This Go code snippet demonstrates how to create and run an external program (`example-prog`) using the `meta.Port` functionality within the Ergo Framework. It initializes `meta.PortOptions`, creates the port, spawns it as a meta-process, and logs the outcome. Errors during creation or spawning are logged. ```go type ActorPort struct { act.Actor } func (ap *ActorPort) Init(args ...any) error { var options meta.PortOptions options.Cmd = "example-prog" // create port metaport, err := meta.CreatePort(options) if err != nil { ap.Log().Error("unable to create Port: %s", err) return err } // spawn meta process id, err := ap.SpawnMeta(metaport, gen.MetaOptions{}) if err != nil { ap.Log().Error("unable to spawn port meta-process: %s", err) return err } ap.Log().Info("started Port (iotxt) %s (meta-process: %s)", options.Cmd, id) return nil } ``` -------------------------------- ### Saturn Configuration Example: General Cluster Settings Source: https://docs.ergo.services/tools/saturn Example `saturn.yaml` configuration for the general cluster, showing how to set default variables for all nodes not explicitly assigned to a specific cluster, and how to override settings for a specific node within the general cluster. ```yaml Clusters: Var1: 123 Cluster@: Var1: 789 node@host: Var1: 456 ``` -------------------------------- ### Create and Spawn meta.WebHandler in Go Source: https://docs.ergo.services/meta-processes/web Demonstrates how to create and spawn a meta.WebHandler for processing HTTP requests. It involves creating an HTTP multiplexer, instantiating the handler with worker options, spawning it as a meta-process, and registering it with the multiplexer. ```go func factory_MyWeb() gen.ProcessBehavior { return &MyWeb{} } type MyWeb struct { act.Actor } // Init invoked on a start this process. func (w *MyWeb) Init(args ...any) error { // create an HTTP request multiplexer mux := http.NewServeMux() // create a root handler meta-process root := meta.CreateWebHandler(meta.WebHandlerOptions{ // use process based on act.WebWorker // and spawned with registered name "mywebworker" Worker: "mywebworker", }) // spawn this meta-process rootid, err := w.SpawnMeta(root, gen.MetaOptions{}) if err != nil { w.Log().Error("unable to spawn WebHandler meta-process: %s", err) return err } // add our meta-process as a handler of HTTP-requests to the mux // since it implements http.Handler interface mux.Handle("/", root) // you can also use your middleware function: // mux.Handle("/", middleware(root))] w.Log().Info("started WebHandler to serve '/' (meta-process: %s)", rootid) // create and spawn web server meta-process // with the mux we created to handle HTTP-requests // // see below... ... return nil } ``` -------------------------------- ### Saturn Configuration Example: Global and Node-Specific Settings Source: https://docs.ergo.services/tools/saturn Example of a `saturn.yaml` configuration file demonstrating how to set global variables for all nodes across all clusters, and how to override specific variables for a particular node. It highlights the use of `.file` for byte array configurations. ```yaml Clusters: Var1: 123 Var2: 12.3 Var3: "123" Var4.file: "./myfile.txt" node@host.local: Var1: 456 ``` -------------------------------- ### Configure Ergo Test Environment Options (Go) Source: https://docs.ergo.services/testing/unit Demonstrates how to configure the Ergo test environment using `unit.Spawn()` with various options. These options allow for simulating different runtime conditions such as log levels, environment variables, parent processes, and node names without modifying production code. This is crucial for comprehensive testing and debugging. ```go // Available options for unit.Spawn() unite.WithLogLevel(gen.LogLevelDebug) // Set log level unite.WithEnv(map[gen.Env]any{"key": "value"}) // Environment variables unite.WithParent(gen.PID{Node: "parent", ID: 100}) // Parent process unite.WithRegister(gen.Atom("registered_name")) // Register with name unite.WithNodeName(gen.Atom("test_node@localhost")) // Node name ``` -------------------------------- ### Establish Connection to Remote Node in Go Source: https://docs.ergo.services/networking/network-stack Demonstrates how to explicitly establish a connection to a remote node using the GetNode method from the gen.Network interface in Go. It shows obtaining a node instance and then retrieving a remote node representation. Dependencies include the 'ergo' and 'gen' packages. ```go func main() { ... // Assuming 'ergo' and 'gen' are imported and node is initialized node, err := ergo.StartNode("node1@localhost", gen.NodeOptions{}) if err != nil { // Handle error return } ... remote, err := node.Network().GetNode("node2@localhost") if err != nil { // Handle error return } // 'remote' is now a gen.RemoteNode interface ... } ``` -------------------------------- ### Start Ergo Node with a Name in Go Source: https://docs.ergo.services/basics/node Demonstrates how to initialize and start an Ergo Node with a unique name. The node's name, in the format '@', determines its network interface for incoming connections. The `ergo.StartNode` function returns a `gen.Node` interface upon successful startup, or an error if initialization fails. ```go import ( "ergo.services/ergo" "ergo.services/ergo/gen" ) func main() { name := "example@localhost" // Start node. Returns gen.Node interface node, err := ergo.StartNode(name, opts) if err != nil { panic(err) } node.Wait() } ``` -------------------------------- ### Demonstrate Logging Best Practices in Go Source: https://docs.ergo.services/testing/unit Illustrates effective logging practices in Go for testability. It contrasts a well-structured log message with a poorly constructed one, emphasizing the benefits of using formatted strings for easier log parsing and assertion in tests. ```go // Good: Structured, predictable format log.Info("User login: user=%s success=%t", userID, success) // Poor: Hard to test reliably log.Info("User " + userID + " tried to login and it " + result) ``` -------------------------------- ### act.SupervisorTypeSimpleOneForOne Source: https://docs.ergo.services/actors/supervisor Documentation for the act.SupervisorTypeSimpleOneForOne, a simplified supervisor that starts child processes on demand via StartChild. ```APIDOC ## act.SupervisorTypeSimpleOneForOne ### Description This supervisor type is a simplified version of `act.SupervisorTypeOneForOne`. It does not start child processes on startup. Instead, child processes are started using the `StartChild` method. The termination of a child process triggers its restart strategy, and child processes are launched without an associated name, allowing multiple processes from one specification. The `KeepOrder` and `DisableAutoShutdown` options in `act.SupervisorSpec.Restart` are ignored for this supervisor type. ### Child Process Specification Describes parameters for starting a child process using `act.SupervisorChildSpec`: * **Name** (gen.Atom): The specification's name. Ignored for `act.SupervisorTypeSimpleOneForOne`. * **Factory, Options, Args**: Parameters needed to launch a new process. * **Significant** (bool): Determines the importance of the child process. Ignored for `act.SupervisorTypeSimpleOneForOne`. ### Restart Strategy Defined by `act.SupervisorRestart` in `act.SupervisorSpec`: * **Strategy** (act.SupervisorStrategy): Specifies the restart strategy type: * `act.SupervisorStrategyTransient`: Default. Restarts on crash, not on normal termination. * `act.SupervisorStrategyTemporary`: No restart occurs. * `act.SupervisorStrategyPermanent`: Any termination triggers a restart. * **Intensity** (int) and **Period** (int): Maximum restart activations allowed within a period (seconds). Exceeding this limit terminates the supervisor and children. * **KeepOrder** (bool): Specifies the order in which child processes are stopped. Ignored for `act.SupervisorTypeSimpleOneForOne`. ### Methods of act.Supervisor * `StartChild(name gen.Atom, args...)`: Starts a child process by its specification name, updating arguments for future restarts. * `AddChild(child act.SupervisorChildSpec)`: Adds a child specification and automatically starts the process. * `EnableChild(name gen.Atom)`: Enables and starts a previously disabled child process. * `DisableChild(name gen.Atom)`: Disables the specification and stops the running process. * `Children()`: Returns a list of `[]act.SupervisorChild` with data on specifications and running processes. ``` -------------------------------- ### Spawning a Meta-process Source: https://docs.ergo.services/basics/meta-process Use the SpawnMeta method to initiate a new meta-process. This method accepts a behavior definition and configuration options. ```APIDOC ## SpawnMeta ### Description Starts a new meta-process. ### Method POST ### Endpoint /websites/ergo_services/spawnMeta ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **behavior** (gen.MetaBehavior) - Required - The behavior definition for the meta-process. - **options** (genMetaOptions) - Required - Configuration options for the meta-process. - **MailboxSize** (integer) - Optional - Size of the meta-process's mailbox. - **SendPriority** (integer) - Optional - Priority for messages sent by the meta-process. - **LogLevel** (string) - Optional - The logging level for the meta-process. ### Request Example ```json { "behavior": { ... }, "options": { "MailboxSize": 100, "SendPriority": 1, "LogLevel": "INFO" } } ``` ### Response #### Success Response (200) - **alias** (gen.Alias) - The identifier for the spawned meta-process. #### Response Example ```json { "alias": "some-meta-process-id" } ``` ``` -------------------------------- ### Implementing HandleGet and Integrating with Pool Source: https://docs.ergo.services/actors/webworker Example of implementing the `HandleGet` method for a `WebWorker` and configuring an `act.Pool` to manage a pool of these workers for load balancing. ```APIDOC ## Implementing HTTP Handlers with WebWorker ### Description This section demonstrates how to implement specific HTTP request handlers, such as `HandleGet`, within a custom `WebWorker` struct. It also shows how to set up an `act.Pool` to manage a collection of these workers for efficient load distribution. ### Method N/A ### Endpoint N/A ### Parameters N/A ### Request Example ```go // // WebWorker // func factory_MyWebWorker() gen.ProcessBehavior { return &MyWebWorker{} } type MyWebWorker struct { act.WebWorker } // Handle GET requests. func (w *MyWebWorker) HandleGet(from gen.PID, writer http.ResponseWriter, request *http.Request) error { w.Log().Info("got HTTP request %q", request.URL.Path) w.WriteHeader(http.StatusOK) return nil } // // Pool of workers // type MyPool struct { act.Pool } func factory_MyPool() gen.ProcessBehavior { return &MyPool{} } // Init invoked on a spawn Pool for the initializing. func (p *MyPool) Init(args ...any) (act.PoolOptions, error) { opts := act.PoolOptions{ WorkerFactory: factory_MyWebWorker, } p.Log().Info("started process pool of MyWebWorker with %d workers", opts.PoolSize) return opts, nil } ``` ### Response N/A ## Example Deployment ### Description An example implementation of a web server using `act.WebWorker` and `act.Pool` for load distribution can be found in the `demo` project within the `ergo-services/examples` repository on GitHub. ### Method N/A ### Endpoint N/A ### Parameters N/A ### Request Example ``` https://github.com/ergo-services/examples/tree/main/demo ``` ### Response N/A ``` -------------------------------- ### Erlang Process Sending Registered Type Source: https://docs.ergo.services/extra-library/network-protocols/erlang Example Erlang code demonstrating how to send data that can be automatically decoded into a registered Go struct type. ```erlang % Assuming 'Pid' is the PID of the Go service % and the Go service has registered a type named 'myvalue' -define(MY_VALUE_ATOM, myvalue). -record(my_value_record, {my_string_field, my_int}). % Send data to the Go service send(Pid, {?MY_VALUE_ATOM, "hello from erlang", 123}). ``` -------------------------------- ### gen.Process Interface Usage in Actor Source: https://docs.ergo.services/basics/generic-types Example of using the gen.Process interface within an actor's Init method to send a message to itself using PID and Send. ```go type myActor struct { act.Actor } func (a *myActor) Init(args ...any) error { // Sending a message to itself using methods PID and Send // that belong to the embedded gen.Process interface a.Send(a.PID(), "hello") } ```