Completed
Push — master ( 956692...a443d7 )
by Tomasz
02:25
created

ZmqServer   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 79.17%

Importance

Changes 8
Bugs 0 Features 3
Metric Value
c 8
b 0
f 3
dl 0
loc 141
wmc 13
lcom 1
cbo 3
ccs 38
cts 48
cp 0.7917
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A run() 0 14 3
A runCommand() 0 13 3
A commandGenerate() 0 11 2
A commandStatus() 0 4 1
A createResponse() 0 7 1
A getZmqSocket() 0 9 1
A setLogger() 0 4 1
1
<?php
2
3
/**
4
 * ZeroMQ interface for cruftflake.
5
 * 
6
 * @author @davegardnerisme
7
 */
8
9
namespace Gendoria\CruftFlake\Zmq;
10
11
use Exception;
12
use Gendoria\CruftFlake\Generator\Generator;
13
use Gendoria\CruftFlake\ServerInterface;
14
use Psr\Log\LoggerAwareInterface;
15
use Psr\Log\LoggerInterface;
16
use Psr\Log\NullLogger;
17
18
class ZmqServer implements ServerInterface, LoggerAwareInterface
19
{
20
    /**
21
     * Cruft flake generator.
22
     * 
23
     * @var Generator
24
     */
25
    private $generator;
26
27
    /**
28
     * DSN.
29
     * 
30
     * @var string
31
     */
32
    private $dsn;
33
34
    /**
35
     * Logger.
36
     * 
37
     * @var LoggerInterface
38
     */
39
    private $logger;
40
    private $debugMode = false;
41
42
    /**
43
     * Constructor.
44
     * 
45
     * @param @inject Generator $generator
46
     * @param string            $dsn       Where socket should be bound. Default 'tcp://*:5599'
47
     * @param bool              $debugMode Debug mode. If set to true, server will only listen for one command, before exiting.
48
     */
49 4
    public function __construct(Generator $generator, $dsn = 'tcp://*:5599', $debugMode = false)
50
    {
51 4
        $this->generator = $generator;
52 4
        $this->dsn = $dsn;
53 4
        $this->logger = new NullLogger();
54 4
        $this->debugMode = $debugMode;
55 4
    }
56
57
    /**
58
     * Run ZMQ interface for generator.
59
     * 
60
     * Req-rep pattern; msgs are commands:
61
     * 
62
     * GEN    = Generate ID
63
     * STATUS = Get status string
64
     */
65 4
    public function run()
66
    {
67 4
        $receiver = $this->getZmqSocket($this->dsn);
68 4
        while (true) {
69 4
            $msg = $receiver->recv();
70 4
            $this->logger->debug('ZMQ server received command: '.$msg);
71 4
            $response = $this->runCommand($msg);
72 4
            $receiver->send(json_encode($response));
73 4
            $this->generator->heartbeat();
74 4
            if ($this->debugMode) {
75 4
                break;
76
            }
77
        }
78 4
    }
79
80 4
    private function runCommand($msg)
81
    {
82
        switch ($msg) {
83 4
            case 'GEN':
84 2
                return $this->commandGenerate();
85 2
            case 'STATUS':
86 1
                return $this->commandStatus();
87 1
            default:
88 1
                $this->logger->debug('Unknown command received: '.$msg);
89
90 1
                return $this->createResponse('UNKNOWN COMMAND', 404);
91 1
        }
92
    }
93
94
    /**
95
     * Create generate command response.
96
     * 
97
     * @return array
98
     */
99 2
    private function commandGenerate()
100
    {
101
        try {
102 2
            $response = $this->createResponse($this->generator->generate());
103 2
        } catch (Exception $e) {
104 1
            $this->logger->error('Generator error: '.$e->getMessage(), array($e, $this));
105 1
            $response = $this->createResponse('ERROR', 500);
106
        }
107
108 2
        return $response;
109
    }
110
111
    /**
112
     * Create status command response.
113
     * 
114
     * @return array
115
     */
116 1
    private function commandStatus()
117
    {
118 1
        return $this->createResponse($this->generator->status());
119
    }
120
121
    /**
122
     * Prepare response.
123
     * 
124
     * @param mixed $message Return message. Anything, which is JSON serializable.
125
     * @param int   $code    Response code.
126
     * 
127
     * @return array
128
     */
129 4
    private function createResponse($message, $code = 200)
130
    {
131
        return array(
132 4
            'code' => $code,
133 4
            'message' => $message,
134 4
        );
135
    }
136
137
    /**
138
     * Get ZMQ socket.
139
     * 
140
     * @param string $dsn DSN, on which ZMQ connection should listen.
141
     *
142
     * @return \ZMQSocket
143
     */
144
    protected function getZmqSocket($dsn)
145
    {
146
        $context = new \ZMQContext();
147
        $receiver = new \ZMQSocket($context, \ZMQ::SOCKET_REP);
148
        $this->logger->debug("Binding to {$dsn}");
149
        $receiver->bind($dsn);
150
151
        return $receiver;
152
    }
153
154
    public function setLogger(LoggerInterface $logger)
155
    {
156
        $this->logger = $logger;
157
    }
158
}
159