Process
What is a Process in Ergo Framework
In Ergo Framework, a process is a lightweight entity that operates on top of a goroutine and is based on the actor model. Each process has a mailbox for receiving incoming messages. The size of the mailbox is determined by the gen.ProcessOptions.MailboxSize
parameter when the process is started. By default, this value is set to zero, which makes the mailbox unlimited in size. Inside the mailbox, there are several queues—Main, System, Urgent, and Log—that prioritize the processing of messages.
Any running process can send messages and make synchronous calls to other processes, including those running on remote nodes. Additionally, a process can spawn new processes, both locally and on remote nodes (see Remote Spawn Process).
Process Identifiers
Processes in Ergo Framework are created and run within the scope of a node. Each process is assigned a unique identifier called gen.PID
when it is started. The gen.PID
consists of several key components:
Node
: name of the node on which the process is running.ID
: unique number that identifies the process within its node.Creation
: property that represents the "incarnation" of the process, meaning the specific instance of the node in which the process was created.
This combination of properties allows for:
Identification Across Nodes: node name is used for routing messages to remote nodes where the process resides. Once routed to the correct node, the process's unique sequential number is used for local message routing on the remote node.
Process Incarnation Handling:
Creation
property allows the system to distinguish between different instances of a node. This property has the same value for all processes within a node's lifecycle. If the node is restarted, theCreation
value changes (it stores the timestamp of the node's startup).
If you attempt to send a message to a process with a gen.PID
that belongs to a previous incarnation of the node, an error gen.ErrProcessIncarnation
will be returned.
This mechanism ensures that processes are accurately identified and that message routing remains reliable, even across restarts of nodes.
gen.ProcessID
A process can also be identified by a name associated with it. You can register such a name when starting a process using the SpawnRegister
method of the gen.Node
interface. Additionally, a process can register its name after it has started by calling the RegisterName
method of the gen.Process
interface.
If you want to change the associated name of a process, you first need to unregister the current name. This is because a process is limited to having only one associated name at a time. The UnregisterName
method of the gen.Process
interface allows you to remove the current name registration.
To send a message to a process by its registered name, you can use the SendProcessID
method of the gen.Process
interface. For making a synchronous request by name, the gen.Process
interface provides the CallProcessID
method.
These methods make it easy to send messages and interact with processes using their associated names, without needing to know their gen.PID
, especially when dealing with remote or dynamically created processes.
To send a message or make a synchronous request to a local process, you can use the universal methods Send
and Call
of the gen.Process
interface, respectively:
gen.Alias
In Ergo Framework, processes have the ability to create temporary identifiers known as aliases. A process can generate an unlimited number of aliases using the CreateAlias
method of the gen.Process
interface. These aliases remain valid throughout the lifetime of the process or until the process explicitly removes them using the DeleteAlias
method of the gen.Process
interface.
Aliases provide additional flexibility by allowing a process to be referenced by multiple temporary identifiers, useful for handling specific tasks or interactions where a unique, temporary process reference is needed.
Process states
A process in Ergo Framework can be in one of the following states:
Init - This is the state of the process during its startup. At this stage, the process is not yet registered in the node, so only a limited set of methods from the
gen.Process
interface are available—such as modifying process properties (environment variables, message compression settings, setting priorities for outgoing messages). Attempts to use methods likeRegisterName
,RegisterEvent
,CreateAlias
,Call*
,Link*
, andMonitor*
will return the errorgen.ErrNotAllowed
. However, methods likeSend*
andSpawn*
remain available in this state.Sleep - This state occurs when the process has no messages in its mailbox, and no goroutine is running for the process. The process is idle and consumes no CPU resources in this state.
Running - When a process receives a message in its mailbox, a goroutine is launched, and the appropriate callback is executed. Once the message has been processed and if there are no other messages in the mailbox, the process returns to the Sleep state, and the goroutine is terminated.
WaitResponse - The process transitions to this state from Running when it makes a synchronous request (
Call*
). The process waits for a response to the request, and once received, it transitions back to the Running stateZombee - This is an intermediate state that occurs when a process was in the Running state but the node forcibly stopped the process using the
Kill
method. In this state, the process cannot access any methods from thegen.Process
interface. After processing the current message and terminating the goroutine, the process transitions from Zombie to Terminated. In this state, the process no longer receives new messages.Terminated - This is the final state of the process before it is removed from the node. Messages are not delivered to a process in this state.
You can retrieve the current state of a process using the ProcessInfo
method of the gen.Node
interface. Alternatively, you can use the State
method of the gen.Process
interface to check the state directly from the process.
These states define the lifecycle of a process and determine what actions it can perform at any given moment in Ergo Framework.
Environment Variables
Each process in Ergo Framework has its own set of environment variables, which can be retrieved using the EnvList()
method of the gen.Process
interface. To modify these variables, the SetEnv(name gen.Env, value any)
method is used; if value
is set to nil
, the environment variable with the specified name will be removed. Environment variable names are case-insensitive, allowing for flexible and dynamic configuration management within processes:
The initialization of a process's environment variables occurs at the moment the process starts. The starting process first inherits the environment variables of the node, then the environment variables of the application and parent process, and finally, the environment variables specified in gen.ProcessOptions
are added.
Process starting
To launch a new process in Ergo Framework, there are two methods:
Both methods are available in the gen.Node
and gen.Process
interfaces.
When using the SpawnRegister
method, the node checks whether the specified name register
can be assigned to the starting process. If the name is already taken by another process, this function will return the error gen.ErrTaken
.
Parent process
Processes launched by the node (using the Spawn*
methods of the gen.Node
interface) are assigned a virtual parent process identifier, known as CorePID. You can retrieve this value using the CorePID
method of the gen.Node
interface.
If a process is launched using the Spawn*
methods of the gen.Process
interface, it becomes a child process. The Parent
method of the gen.Process
interface in the child process will return the identifier of the process that launched it.
Attempting to send an exit signal to a parent process using the SendExit
method of the gen.Process
interface will result in the error gen.ErrNotAllowed
.
Additionally, the parent process identifier is used in handling exit signals in act.Actor
(see the section on TrapExit in Actor).
Process leader
Each process in Ergo Framework has a process leader identifier, in addition to the parent process identifier. You can retrieve this identifier using the Leader
method of the gen.Process
interface. When a process is started by the node, its process leader is set to the virtual identifier CorePID. If the process is started by another process, the child process inherits the leader identifier from its parent process.
During process startup, it is also possible to explicitly set a process leader using the Leader
option in gen.ProcessOption
. This is commonly done when starting child processes in act.Supervisor
. While the process leader identifier does not influence the operational logic of processes, it serves an informational role and can be used within your application's logic as needed.
gen.ProcessFactory
To start a process in Ergo Framework, you need to specify a factory
argument, which is a factory function. This function must return an object that implements the gen.ProcessBehavior
interface. This is a low-level interface that is already implemented in general-purpose actors (such as act.Actor
, act.Supervisor
, etc.). Therefore, in most cases, you only need to embed the required actor into your object to satisfy the gen.ProcessBehavior
interface.
Example:
gen.ProcessOptions
The options
parameter in the Spawn
or SpawnRegister
functions allows you to configure various parameters for the process being launched:
MailboxSize
: defines the size of the mailbox. If not specified, the mailbox will be unlimited in size.Leader
: sets the leader of the process group. If not specified, the leader value is inherited from the parent process. This setting is informational and does not affect the process itself but can be used in your application's logic. Typically, this is set by supervisor processes.Compression
: specifies the message compression settings when sending messages over the network to remote nodes. This option is ignored if the recipient is a local process.SendPriority
: allows you to set the priority for sent messages. There are three priority levels:gen.MessagePriorityNormal
: Messages are delivered to the Main queue of the recipient's mailbox.gen.MessagePriorityHigh
: Messages are delivered to the System queue.gen.MessagePriorityMax
: Highest-priority messages are delivered to the Urgent queue of the recipient's mailbox.
ImportantDelivery
: enables the important flag for messages sent to remote processes. When enabled, the remote node will send an acknowledgment that the message was delivered to the recipient's mailbox. If the message cannot be delivered, an error (e.g.,gen.ErrProcessTerminated
,gen.ProcessUnknown
,gen.ProcessMailboxFull
) will be returned. You can also manage this flag using theSetImportantDelivery
method of thegen.Process
interface. This flag only applies to messages sent via theSendPID
,SendProcessID
, andSendAlias
methods or requests made usingCallPID
,CallProcessID
, orCallAlias
methods ofgen.Process
. To force a message to be sent with the important flag, use theSendImportant
orCallImportant
methods ofgen.Process
.Fallback
: specifies a fallback process to which messages will be redirected in the event that the recipient's mailbox is full. Each such message is wrapped in thegen.MessageFallback
structure. This option is ignored if the recipient process's mailbox is unlimited.LinkParent
: Automatically creates a link with the parent process when the process is started (after successful initialization). This option is ignored if the process is started by the node.LinkChild
: Automatically creates a link with a child process upon its successful startup (after successful initialization). This option is ignored if the process is started by the node.Env
: Sets the environment variables for the process.
During the initialization stage, processes do not have access to linking methods (Link*
from the gen.Process
interface). However, the LinkParent
and LinkChild
options provide a way to bypass this limitation when launching child processes. These options allow the process to automatically create links with the parent and child processes after successful initialization, ensuring that linking is established even during the startup phase
Process termination
In Ergo Framework, a process can be terminated in the following ways:
Forcefully: process can be terminated by force using the
Kill
method provided by thegen.Node
interface.Sending an Exit Signal: you can stop a process by sending it an exit signal with a specified reason. This is done using the
SendExit
method, which is available in both thegen.Node
andgen.Process
interfaces. The exit signal is always delivered with the highest priority and placed in the Urgent queue. Inact.Actor
, there is a mechanism to intercept exit signals, allowing them to be handled like normalgen.MessageExit*
messages. More information on this mechanism can be found in the Actor section. Sending an exit signal to yourself, your parent process, or the process leader is not allowed. In such cases, theSendExit
method will return the errorgen.ErrNotAllowed
.Self-Termination: A process can terminate itself by returning a non-
nil
value (of typeerror
) from its message handling callback. The returned value will be treated as the termination reason, and the process will be terminated. You can usegen.TerminateReasonNormal
orgen.TerminateReasonShutdown
for normal shutdown scenarios.Panic: If a panic occurs during message processing, the process will be terminated with the reason
gen.TerminateReasonPanic
.
Upon termination, all resources associated with the process are released:
All events registered by the process are unregistered.
Any associated name, if registered, is freed.
Aliases, links, and monitors created by the process are removed.
The process is removed from the logging system if it was previously registered as a logger.
All meta-processes launched by the process are terminated.
Process information
You can retrieve summary information about a process using the ProcessInfo
method of the gen.Node
interface or the Info
method of the gen.Process
interface. Both methods return a gen.ProcessInfo
structure containing detailed information about the process.
Last updated