Actor
An actor in Ergo Framework implements the low-level gen.ProcessBehavior
interface. To launch a process based on act.Actor
, you need to create an object with an embedded act.Actor
and implement a factory function for it. For example:
act.Actor
uses the act.ActorBehavior
interface to interact with your object. This interface defines a set of callback methods:
All methods in the act.ActorBehavior
interface are optional, allowing you to implement only the necessary callbacks in your object. Since act.Actor
embeds the gen.Process
interface, you can directly use its methods from within your actor object.
Example:
Process Initialization
Process initialization begins when act.Actor
invokes the Init
method of the act.ActorBehavior
interface, passing the args
provided during Spawn
(or SpawnRegister
). If Init
completes successfully, the node registers the process, allowing it to receive messages or synchronous requests. If Init
fails, Spawn
(or SpawnRegister
) returns the error. It's important to note that during initialization, the process is not yet registered with the node, limiting access to certain methods of the embedded gen.Process
interface until the process is fully initialized.
Handling Asynchronous Messages and Synchronous Requests
The process mailbox contains several queues: Main, System, Urgent, and a special Log queue. In act.Actor
, messages are processed in the following order: Urgent, System, Main, and then Log.
Asynchronous messages are sent using the Send
method of the gen.Node
or gen.Process
interface. Upon receiving such a message, act.Actor
calls the HandleMessage
method of the gen.ActorBehavior
interface.
For synchronous requests, the HandleCall
callback method is invoked in an actor based on act.Actor
. The result returned by this method is sent as the response to the request.
A process can send asynchronous messages to itself, but attempting to make a synchronous request to itself will return the error gen.ErrTimeout
..
act.Actor
also allows handling synchronous requests asynchronously. This feature lets you delegate the processing of synchronous requests to other processes or delay the response. To do this, the HandleCall
method should return nil
, and you should use the SendResponse
method of the gen.Process
interface to send the response. You must provide the gen.PID
of the requesting process and the gen.Ref
reference of the request.
For debugging or monitoring the internal state, the Inspect
method allows high-priority synchronous requests. In act.Actor
, this triggers the HandleInspect
method. This feature is widely used in the Observer tool.
If the actor process is registered as a logger, the HandleLog
method is called when log messages (gen.MessageLog
) are received, generated using the gen.Log
interface. If the actor process has subscribed to events using the LinkEvent
or MonitorEvent
methods of gen.Process
, the HandleEvent
method is called when an event message is received.
Process Termination
To stop a process, simply return a non-nil error
value from the message-handling callback. After termination, the Terminate
callback method will be called, with the reason
argument being the returned error value.
Additionally, you can terminate a process using predefined constants like:
gen.TerminateReasonNormal
for a normal (non-failure) termination.gen.TerminateReasonKill
when the process is forcibly stopped using theKill
method from thegen.Node
interface.
In Ergo Framework, two additional termination reasons are defined:
gen.TerminateReasonPanic: Occurs when a panic happens during message processing.
gen.TerminateReasonShutdown: This termination reason can be sent by the parent process or the node when the node is stopped using the
StopForce
method of thegen.Node
interface. It is not considered a failure.
At the moment the Terminate
callback is invoked, the process has already been removed from the node. Therefore, most methods of the gen.Process
interface will return the gen.ErrNotAllowed
error.
SplitHandle
The SplitHandle
option allows an actor to call the callback methods of the act.ActorBehavior
interface based on the process identifier used to send a message or make a synchronous call to your process. You can enable this option using the SetSplitHandle(split bool)
method defined in act.Actor
. To check the current value of this option, use the SplitHandle
method. Here is an example usage:
If your process has a registered associated name and receives a message using that name, act.Actor
will call the HandleMessageName
callback. The name
argument will be the value used to send the message. For synchronous requests, the HandleCallName
callback will be invoked.
If a process alias (gen.Alias
) was used, the callbacks HandleMessageAlias
and HandleCallAlias
will be triggered for messages and synchronous requests, respectively. This enables customized handling based on the way the message or request was sent.
TrapExit - handling exit-signal
In Ergo Framework, an exit signal can be sent to your process by another process or node using the SendExit
method from the gen.Process
or gen.Node
interfaces. It can also be generated by the node if your process had a link created via the Link*
methods in the gen.Process
interface. By default, when an actor receives an exit signal, it terminates and calls the Terminate
callback with the reason specified in the exit signal.
To prevent your actor from terminating upon receiving an exit signal, you can enable the option to intercept such signals. This can be done using the SetTrapExit(trap bool)
method in act.Actor
. The default value is false
, but you can enable it at any time, for example, during initialization:
When the TrapExit
option is enabled, act.Actor
converts exit signals into standard gen.MessageExit*
messages:
gen.MessageExitPID: The source of the exit signal was a process.
gen.MessageExitProcessID: The source was
gen.ProcessID
(a link created usingLinkProcessID
).gen.MessageExitAlias: The source was
gen.Alias
(link created usingLinkAlias
).gen.MessageExitEvent: The source was
gen.Event
(link created usingLinkEvent
).gen.MessageExitNode: The source was a network connection with a node (link created using
LinkNode
).
Scenarios where the exit signal cannot be intercepted:
Parent Process Sends Exit: When the parent process sends an exit signal via
SendExit
using thegen.Process
interface, it cannot be intercepted.Parent Process Terminates: If the parent process, with which a link was created via
gen.PID
(usingLink
orLinkPID
), terminates, or if the parent process used thegen.ProcessOptions.LinkParent
option during child process startup.
In these cases, the actor will terminate, and the Terminate
callback will be called, even with TrapExit
enabled. All other exit signals can be intercepted when TrapExit
is active.
Last updated