# 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](https://metacpan.org/pod/Zing::Watcher)

# LIBRARIES

This package uses type constraints from:

[Zing::Types](https://metacpan.org/pod/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](https://metacpan.org/pod/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](https://metacpan.org/pod/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"](https://metacpan.org/pod/Zing::Types#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](https://metacpan.org/pod/Zing::Channel): Shared Communication
- [Zing::Data](https://metacpan.org/pod/Zing::Data): Process Data
- [Zing::KeyVal](https://metacpan.org/pod/Zing::KeyVal): Key/Value Store
- [Zing::Mailbox](https://metacpan.org/pod/Zing::Mailbox): Process Mailbox
- [Zing::PubSub](https://metacpan.org/pod/Zing::PubSub): Pub/Sub Store
- [Zing::Queue](https://metacpan.org/pod/Zing::Queue): Message Queue
- [Zing::Registry](https://metacpan.org/pod/Zing::Registry): Process Registry
- [Zing::Repo](https://metacpan.org/pod/Zing::Repo): Generic Store
- [Zing::Store](https://metacpan.org/pod/Zing::Store): Storage Abstraction

## processes

These base classes implement the underlying process (actor) logic:

- [Zing](https://metacpan.org/pod/Zing): Process Wrapper
- [Zing::Kernel](https://metacpan.org/pod/Zing::Kernel): Kernel Process
- [Zing::Launcher](https://metacpan.org/pod/Zing::Launcher): Scheme Launcher
- [Zing::Process](https://metacpan.org/pod/Zing::Process): Processing Unit
- [Zing::Ring](https://metacpan.org/pod/Zing::Ring): Process Ring
- [Zing::Scheduler](https://metacpan.org/pod/Zing::Scheduler): Scheme Launcher
- [Zing::Simple](https://metacpan.org/pod/Zing::Simple): Simple Process
- [Zing::Single](https://metacpan.org/pod/Zing::Single): Single Process
- [Zing::Spawner](https://metacpan.org/pod/Zing::Spawner): Scheme Spawner
- [Zing::Watcher](https://metacpan.org/pod/Zing::Watcher): Watcher Process
- [Zing::Worker](https://metacpan.org/pod/Zing::Worker): Worker Process

## ready-made

These classes are ready-made process implementations using callbacks:

- [Zing::Zang](https://metacpan.org/pod/Zing::Zang): Process Implementation
- [Zing::Zang::Launcher](https://metacpan.org/pod/Zing::Zang::Launcher): Process Launcher
- [Zing::Zang::Simple](https://metacpan.org/pod/Zing::Zang::Simple): Process Performer
- [Zing::Zang::Single](https://metacpan.org/pod/Zing::Zang::Single): Single-Task Process
- [Zing::Zang::Spawner](https://metacpan.org/pod/Zing::Zang::Spawner): Process Spawner
- [Zing::Zang::Watcher](https://metacpan.org/pod/Zing::Zang::Watcher): Process Watcher
- [Zing::Zang::Worker](https://metacpan.org/pod/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)
