54a8 Worker patterns - Telecomix Crypto Munitions Bureau

Worker patterns

From Telecomix Crypto Munitions Bureau

Jump to: navigation, search

Code in erlang, when structed to be compatible with the Open Telecom Platform (OTP), essentially follows the idea that everything is either a worker or a supervisor.


Workers are used to perform tasks

  • ANY tasks

Supervisors are used to monitor workers

  • supervisors can also supervise other supervisors
  • sends signals about code update/downgrade
  • monitors if any worker dies, and takes action if that happens


[edit] OTP standard workers

There are three standard worker behaviors in OTP. You probably need to add your own non-standard workers for more specific tasks.

[edit] The model

Image:genX yourcode.png

gen_* is a behavior that you implement. There are three standard OTP behaviors. When anyone does something with your code, they will call one of the functions in gen_* that will in turn send a message to your code. Your callback function will then return a value that is then sent back to the caller.

The gen_* works a bit like a wrapper that allows you to easily write complex and reliable code quickly. It hides all the error-prone and repetitive things so that you can focus on doing creative work instead.

Much of the APIs are reused and can be found in all behaviors. Some functions can only be found in specific behaviors. Below is a more detailed description.


[edit] Common API

Remember the colors from the previous section?

  • Red means that its part of the gen_* API.
  • Green means that its a callback function in your code.

[edit] API found in all gen_*

  • start_link() creates a worker and attach it to a supervisor hierarchy
  • start() creates a worker and does not attach it to a hierarchy
  • stop() destroys the worker

Both start_link() and start() will result in that init() is called in your code. stop() results in that terminate() is called in your code.

[edit] Callback functions exist in all worker behaviors

  • init() called when your worker is just starting
  • handle_info() tells you about timeouts and when unidentified messages are sent to you
  • terminate() tells you that your code is being shut down
  • code_update() supervisor informs worker that it should update/downgrade its code



[edit] API only found in gen_server

Image:gen_server.png

gen_server is used to create processes that are mostly meant to respond to messages. call() and multi_call() sends synchronous messages to your process, while cast() and abcast() are used for sending asynchronous messages. multi_call() and abcast() are used for sending messages to a cluster (if you are running the same server at multiple machines in a cluster)

handle_call() replies to synchronous messages. It often need to reply within a specified amount of time, otherwise an error will be reported via handle_info().

handle_cast() is used to receive asynchronous messages. It does not need to reply.

[edit] API only found in gen_fsm

Image:gen_fsm.png

gen_fsm is used for describing finite state machines. You use send_event() to notify the FSM that an event has occurred that potentially should result in a state transition. Each state in the FSM has its own callback function for handling incoming events. Actions taken by these callback functions can be anything, there is no standard for this (use your creativity).

send_all_state_event() is used to send messages to the FSM that does not depend on the FSM to be in a specific state.

[edit] API only found in gen_event

Image:gen_event.png

Event managers are like hubs. Event handlers can be attached to the event managers via add_handler(). Whenever anyone uses notify() to send an event to the event handler, the event handler will forward the event to all event handlers that are attached.

Typical sequence:

  1. create event manager using start_link()
  2. add at least zero event handlers to the event handler, using add_handler()
  3. send event to event manager. notify()
    • the event is sent to all attached event handlers. handle_event() is called.
  4. delete_handler() will remove an event handler.
  5. stop() removes the event handlers you did not delete, and then removes the event manager.

Event handlers can be much more complicated than this. But they usually just print errors into files, etc.

[edit] Supervisors

Supervisors can supervise both other supervisors and workers, while workers can only perform their designated tasks. This means that software can (SHOULD) be structured in pyramide-like trees.

If a problem occurs in a worker process, its supervisor will be notified. If the problem can not be solved by the local supervisor, the supervisor above that one will try to solve the problem, and so on. Depending on how bad the problem is, either a single worker will be restarted, or an entire subsystem can be restarted.

The idea is that SYSTEM FAILURE IS NOT AN OPTION. So, erlang tries to solve that using these supervisor hierarchies. Rather than trying to make software without errors, erlang takes the approach of making software that is capable of recover from failure.

[edit] Read more

Personal tools
0