Completed
Push — master ( 693b46...956692 )
by Tomasz
02:40
created

ZmqServer::runCommand()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 12
ccs 9
cts 9
cp 1
rs 9.4285
cc 3
eloc 9
nc 3
nop 1
crap 3
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
    /**
22
     * Cruft flake generator.
23
     * 
24
     * @var Generator
25
     */
26
    private $generator;
27
28
    /**
29
     * DSN.
30
     * 
31
     * @var string
32
     */
33
    private $dsn;
34
35
    /**
36
     * Logger.
37
     * 
38
     * @var LoggerInterface
39
     */
40
    private $logger;
41
    private $debugMode = false;
42
43
    /**
44
     * Constructor.
45
     * 
46
     * @param @inject Generator $generator
47
     * @param string            $dsn       Where socket should be bound. Default 'tcp://*:5599'
48
     * @param bool              $debugMode Debug mode. If set to true, server will only listen for one command, before exiting.
49
     */
50 4
    public function __construct(Generator $generator, $dsn = 'tcp://*:5599', $debugMode = false)
51
    {
52 4
        $this->generator = $generator;
53 4
        $this->dsn = $dsn;
54 4
        $this->logger = new NullLogger();
55 4
        $this->debugMode = $debugMode;
56 4
    }
57
58
    /**
59
     * Run ZMQ interface for generator.
60
     * 
61
     * Req-rep pattern; msgs are commands:
62
     * 
63
     * GEN    = Generate ID
64
     * STATUS = Get status string
65
     */
66 4
    public function run()
67
    {
68 4
        $receiver = $this->getZmqSocket($this->dsn);
69 4
        while (true) {
70 4
            $msg = $receiver->recv();
71 4
            $this->logger->debug('ZMQ server received command: ' . $msg);
72 4
            $response = $this->runCommand($msg);
73 4
            $receiver->send(json_encode($response));
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 1
                return $this->createResponse('UNKNOWN COMMAND', 404);
90 1
        }
91
    }
92
93
    /**
94
     * Create generate command response.
95
     * 
96
     * @return array
97
     */
98 2
    private function commandGenerate()
99
    {
100
        try {
101 2
            $response = $this->createResponse($this->generator->generate());
102 2
        } catch (Exception $e) {
103 1
            $this->logger->error('Generator error: ' . $e->getMessage(), array($e, $this));
104 1
            $response = $this->createResponse('ERROR', 500);
105
        }
106
107 2
        return $response;
108
    }
109
110
    /**
111
     * Create status command response.
112
     * 
113
     * @return array
114
     */
115 1
    private function commandStatus()
116
    {
117 1
        return $this->createResponse($this->generator->status());
118
    }
119
120
    /**
121
     * Prepare response.
122
     * 
123
     * @param mixed $message Return message. Anything, which is JSON serializable.
124
     * @param int   $code    Response code.
125
     * 
126
     * @return array
127
     */
128 4
    private function createResponse($message, $code = 200)
129
    {
130
        return array(
131 4
            'code' => $code,
132 4
            'message' => $message,
133 4
        );
134
    }
135
136
    /**
137
     * Get ZMQ socket.
138
     * 
139
     * @param string $dsn DSN, on which ZMQ connection should listen.
140
     *
141
     * @return \ZMQSocket
142
     */
143
    protected function getZmqSocket($dsn)
144
    {
145
        $context = new \ZMQContext();
146
        $receiver = new \ZMQSocket($context, \ZMQ::SOCKET_REP);
147
        $this->logger->debug("Binding to {$dsn}");
148
        $receiver->bind($dsn);
149
150
        return $receiver;
151
    }
152
153
    public function setLogger(LoggerInterface $logger)
154
    {
155
        $this->logger = $logger;
156
    }
157
158
}
159