NAME Zing - Multi-Process Management System ABSTRACT Actor Toolkit and Multi-Process Management System SYNOPSIS use Zing; my $zing = Zing->new(scheme => ['MyApp', [], 1]); # $zing->execute; DESCRIPTION This distribution includes an actor-model architecture toolkit and multi-process management system which provides primatives for building resilient, reactive, concurrent, distributed message-driven applications in Perl 5. If you're unfamiliar with this architectural pattern, learn more about "the actor model" <https://en.wikipedia.org/wiki/Actor_model>. INHERITS This package inherits behaviors from: Zing::Watcher LIBRARIES This package uses type constraints from: Zing::Types ATTRIBUTES This package has the following attributes: scheme scheme(Scheme) This attribute is read-only, accepts (Scheme) values, and is required. METHODS This package implements the following methods: start start() : Kernel The start method builds a Zing::Kernel and executes its event-loop. start example #1 # given: synopsis $zing->start; COMMANDS Given the following process (actor): # in lib/MyApp.pm package MyApp; use parent 'Zing::Single'; sub perform { # do something (once) } 1; With an application cartridge specifying 4 forks: # in app/myapp ['MyApp', [], 4] The zing command-line application lets you manage Zing applications from the command-line using these commands: start $ zing start app/myapp The start command loads an application cartridge which returns a "scheme" and runs it as a daemon. stop $ zing stop app/myapp The stop command finds a running application by its PID (process ID) and terminates the process. logs $ zing logs The logs command taps the centralized log source and outputs new events to STDOUT (standard output). PRIMATIVES This distribution provides a collection of actor-model primitives which can be used to create sophisticated and powerful distributed systems, organized within intricate process topologies. The following is a directory of those primitives listed by classification: messaging These classes facilitate message-passing and communications: * Zing::Channel: Shared Communication * Zing::Data: Process Data * Zing::KeyVal: Key/Value Store * Zing::Mailbox: Process Mailbox * Zing::PubSub: Pub/Sub Store * Zing::Queue: Message Queue * Zing::Registry: Process Registry * Zing::Repo: Generic Store * Zing::Store: Storage Abstraction processes These base classes implement the underlying process (actor) logic: * Zing: Process Wrapper * Zing::Kernel: Kernel Process * Zing::Launcher: Scheme Launcher * Zing::Process: Processing Unit * Zing::Ring: Process Ring * Zing::Scheduler: Scheme Launcher * Zing::Simple: Simple Process * Zing::Single: Single Process * Zing::Spawner: Scheme Spawner * Zing::Watcher: Watcher Process * Zing::Worker: Worker Process ready-made These classes are ready-made process implementations using callbacks: * Zing::Zang: Process Implementation * Zing::Zang::Launcher: Process Launcher * Zing::Zang::Simple: Process Performer * Zing::Zang::Single: Single-Task Process * Zing::Zang::Spawner: Process Spawner * Zing::Zang::Watcher: Process Watcher * Zing::Zang::Worker: Worker Process FEATURES All features are implemented using classes and objects. The following is a list of features currently enabled by this toolkit: actor-model use Zing::Process; my $p1 = Zing::Process->new(name => 'p1'); my $p2 = Zing::Process->new(name => 'p2'); $p1->mailbox->send($p2->name, { action => 'greeting' }); This distribution provides a toolkit for creating processes (actors) which can be run in isolation and which communicate with other processes through message-passing. asynchronous # in process (1) use Zing::Process; my $p1 = Zing::Process->new(name => 'p1'); $p1->execute; # in process (2) use Zing::Process; my $p2 = Zing::Process->new(name => 'p2'); my $friends = $p2->registry->keys; for my $friend (@$friends) { # send each registered process a message $p2->send($friend, { discovery => $p2->name }); } $p2->execute; This distribution provides a multi-process management system which allows processes to be deployed and managed separately having the ability to communicate across threads of execution. atomicity # in process (1) use Zing::KeyVal; my $i = 0; my $kv = Zing::KeyVal->new(name => 'stash'); while ($i < 1_000) { $kv->send('random', { value => 1 }); # my $data = $kv->recv('random'); } # in process (2) use Zing::KeyVal; my $i = 0; my $kv = Zing::KeyVal->new(name => 'stash'); while ($i < 1_000) { $kv->send('random', { value => 2 }); # my $data = $kv->recv('random'); } This distribution provides data storage abstractions which perform atomic reads and write by leveraging Redis <https://redis.io> as the default data storage backend. chainable use Zing::Process; use Zing::Ring; my $p1 = Zing::Process->new(name => 'p1'); my $p2 = Zing::Process->new(name => 'p2'); my $ring = Zing::Ring->new(processes => [$p1, $p2]); $ring->execute; This distribution provides a mechanism for chaining (i.e. joining) two or more processes together and executing them in a turn-based manner. This ability allows you to design complex hierarchical process topologies. channels # in process (1) use Zing::Channel; my $chan = Zing::Channel->new(name => 'chat'); while (1) { if (my $data = $chan->recv) { # broadcast received warn $data->{text}; } } # in process (2) use Zing::Channel; my $chan = Zing::Channel->new(name => 'chat'); while (1) { if (my $data = $chan->recv) { # broadcast received warn $data->{text}; } } This distribution provides the means for braodcasting and communicating to multiple processes simulaneously through channels which are similar to FIFO queues. clusterable # in process (1) on cluster (1) use Zing::Queue; my $queue = Zing::Queue->new(name => 'tasks', target => 'global'); # pull from global queue $queue->recv; # in process (1) on cluster (2) use Zing::Queue; my $queue = Zing::Queue->new(name => 'tasks', target => 'global'); # pull from global queue $queue->recv; This distribution provides support cross-cluster communication and thus operations. Using federated Redis as the data storage backend means you can scale your deployments without changing your implementations. distributed # in process (1..n) on cluster (1) use Zing; my $zing = Zing->new(scheme => ['MyApp', [], 16]); $zing->execute; # in process (1..n) on cluster (2) use Zing; my $zing = Zing->new(scheme => ['MyApp', [], 16]); $zing->execute; # in process (1..n) on cluster (3) use Zing; my $zing = Zing->new(scheme => ['MyApp', [], 16]); $zing->execute; This distribution provides a collection of actor-model primitives which can be used to create sophisticated and powerful distributed systems, organized within intricate process topologies. event-driven # in process (1) use Zing::Process; my $p1 = Zing::Process->new(name => 'file-upload'); $p1->execute; # in process (2) use Zing::Process; my $p2 = Zing::Process->new(name => 'text-translate'); $p2->execute; This distribution provides all the prerequisites needed to develop scalable reactive event-driven applications distributed across one or several servers. fifo-queues # in process (1) use Zing::Queue; my $queue = Zing::Queue->new(name => 'tasks'); # pull from global queue $queue->send({ command => { ... } }); $queue->send({ command => { ... } }); $queue->send({ command => { ... } }); $queue->send({ command => { ... } }); # in process (2) use Zing::Queue; my $queue = Zing::Queue->new(name => 'tasks'); # pull from FIFO queue $queue->recv; This distribution provides high-performance FIFO message queues which enhance messaging across processes when the order of operations and events is critical and where duplicates can't be tolerated. hot-reloadable use Zing; use Zing::Daemon; my $daemon = Zing::Daemon->new( name => 'myapp-sleep', app => Zing->new(scheme => ['MyApp::Sleep', [], 4]) ); $daemon->execute; # pid 12345 # $ kill -USR2 12345 This distribution provides zero-downtime through hot-reloading which is where the process watchers (supervisors) keep the app running and gracefully reload child processes at runtime. log-shipping use Zing::Zang; my $zang = Zing::Zang->new(on_perform => sub { my ($self) = @_; $self->log->fatal('something went wrong'); return; }); # $zang->execute; # tap the logs using the command-line tool # $ zing logs This distribution provides the ability to ship the logs of individual processes to a specific centralized channel which can be tapped asynchronously, especially by the command-line tool. mailboxes use Zing::Process; my $p1 = Zing::Process->new(name => 'p1'); my $p2 = Zing::Process->new(name => 'p2'); $p1->mailbox->send($p2->name, { say => 'ehlo' }); my $message = $p2->mailbox->recv; $p2->mailbox->reply($message, { say => 'helo' }); This distribution provides every process with its own unique mailbox which can receive messages from other processes as a means of cooperating through message passing. management use Zing::Kernel; my $kernel = Zing::Kernel->new(scheme => ['MyApp::Logger', [], 2]); $kernel->execute; This distribution provides a kernel process that can be used to manage the deployment of child processes and is used to wrap cartridges by the command-line tool when daemonizing process. multitasking use Zing::Zang; my $zang = Zing::Zang->new( on_perform => sub { # do something }, on_receive => sub { # handle something }, ); $zang->execute; This distribution provides all processes with an event-loop that allows them to perform multiple operations in sequence and supports operating in a non-blocking manner. non-blocking use Zing::Zang; my $zang = Zing::Zang->new( on_perform => sub { my ($self) = @_; $self->defer({ command => {...} }); return; }, on_receive => sub { my ($self, $from, $data) = @_; # from myself return unless $self->name eq $from; # $data->{command} ... return; } ); $zang->exercise; This distribution provides features that allow processes to operate in a non-blocking manner, yielding and deferring operations, and chunking workloads. parallelism use Zing::Process; my $p1 = Zing::Process->new; my $f1 = $p1->spawn(['MyApp', [id => 12345] 1]); my $f2 = $p1->spawn(['MyApp', [id => 12346] 1]); This distribution provides multiple ways of executing operations in parallel, including spawning processes via forking with the guarantee of not creating zombie processes. supervisors use Zing::Zang::Watcher; my $zang = Zing::Zang::Watcher->new( scheme => ['MyApp', [] 8] ); $zang->exercise; This distribution provides watcher processes which to supervise child processes but also are capable of multitasking and performing other operations while monitoring supervised processes. SEE ALSO The Actor Model <https://en.wikipedia.org/wiki/Actor_model> Concurrent Computation <https://www.amazon.com/Actors-Concurrent-Computation-Distributed-Systems/dp/026251141X> Concurrency in Go/Erlang <https://www.youtube.com/watch?v=2yiKUIDFc2I> The Akka Project <https://github.com/akka/akka> The Actorkit Project <https://github.com/influx6/actorkit> The Orleans Project <http://dotnet.github.io/orleans> The Pyakka Project <https://github.com/jodal/pykka> The Reactive Manifesto <http://www.reactivemanifesto.org> AUTHOR Al Newkirk, awncorp@cpan.org LICENSE Copyright (C) 2011-2019, Al Newkirk, et al. This is free software; you can redistribute it and/or modify it under the terms of the The Apache License, Version 2.0, as elucidated in the "license file" <https://github.com/iamalnewkirk/zing/blob/master/LICENSE>. PROJECT Wiki <https://github.com/iamalnewkirk/zing/wiki> Project <https://github.com/iamalnewkirk/zing> Initiatives <https://github.com/iamalnewkirk/zing/projects> Milestones <https://github.com/iamalnewkirk/zing/milestones> Contributing <https://github.com/iamalnewkirk/zing/blob/master/CONTRIBUTE.md> Issues <https://github.com/iamalnewkirk/zing/issues>