Completed
Push — master ( d2d655...b06c47 )
by Tomasz
02:36
created

ZmqServer   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 79.17%

Importance

Changes 5
Bugs 0 Features 2
Metric Value
wmc 12
c 5
b 0
f 2
lcom 1
cbo 3
dl 0
loc 138
ccs 38
cts 48
cp 0.7917
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
B run() 0 24 5
A commandGenerate() 0 11 2
A commandStatus() 0 4 1
A createResponse() 0 7 1
A __construct() 0 7 1
A getZmqSocket() 0 9 1
A setLogger() 0 4 1
1
<?php
2
/**
3
     * ZeroMQ interface for cruftflake.
4
     * 
5
     * @author @davegardnerisme
6
     */
7
8
namespace Gendoria\CruftFlake\Zmq;
9
10
use Exception;
11
use Gendoria\CruftFlake\Generator\Generator;
12
use Gendoria\CruftFlake\ServerInterface;
13
use Psr\Log\LoggerAwareInterface;
14
use Psr\Log\LoggerInterface;
15
use Psr\Log\NullLogger;
16
17
class ZmqServer implements ServerInterface, LoggerAwareInterface
18
{
19
    /**
20
     * Cruft flake generator.
21
     * 
22
     * @var Generator
23
     */
24
    private $generator;
25
26
    /**
27
     * DSN
28
     * 
29
     * @var string
30
     */
31
    private $dsn;
32
33
    /**
34
     * Logger.
35
     * 
36
     * @var LoggerInterface
37
     */
38
    private $logger;
39
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
            switch ($msg) {
72 4
                case 'GEN':
73 2
                    $response = $this->commandGenerate();
74 2
                    break;
75 2
                case 'STATUS':
76 1
                    $response = $this->commandStatus();
77 1
                    break;
78 1
                default:
79 1
                    $this->logger->debug('Unknown command received: '.$msg);
80 1
                    $response = $this->createResponse('UNKNOWN COMMAND', 404);
81 1
                    break;
82 1
            }
83 4
            $receiver->send(json_encode($response));
84 4
            if ($this->debugMode) {
85 4
                break;
86
            }
87
        }
88 4
    }
89
90
    /**
91
     * Create generate command response.
92
     * 
93
     * @return array
94
     */
95 2
    private function commandGenerate()
96
    {
97
        try {
98 2
            $response = $this->createResponse($this->generator->generate());
99 2
        } catch (Exception $e) {
100 1
            $this->logger->error('Generator error: '.$e->getMessage(), array($e, $this));
101 1
            $response = $this->createResponse('ERROR', 500);
102
        }
103
104 2
        return $response;
105
    }
106
107
    /**
108
     * Create status command response.
109
     * 
110
     * @return array
111
     */
112 1
    private function commandStatus()
113
    {
114 1
        return $this->createResponse($this->generator->status());
115
    }
116
117
    /**
118
     * Prepare response.
119
     * 
120
     * @param mixed $message Return message. Anything, which is JSON serializable.
121
     * @param int   $code    Response code.
122
     * 
123
     * @return array
124
     */
125 4
    private function createResponse($message, $code = 200)
126
    {
127
        return array(
128 4
            'code' => $code,
129 4
            'message' => $message,
130 4
        );
131
    }
132
133
    /**
134
     * Get ZMQ socket.
135
     * 
136
     * @param string $dsn DSN, on which ZMQ connection should listen.
137
     *
138
     * @return \ZMQSocket
139
     */
140
    protected function getZmqSocket($dsn)
141
    {
142
        $context = new \ZMQContext();
143
        $receiver = new \ZMQSocket($context, \ZMQ::SOCKET_REP);
144
        $this->logger->debug("Binding to {$dsn}");
145
        $receiver->bind($dsn);
146
147
        return $receiver;
148
    }
149
150
    public function setLogger(LoggerInterface $logger)
151
    {
152
        $this->logger = $logger;
153
    }
154
}
155