Completed
Pull Request — master (#16)
by Jan
26:20 queued 11:22
created

JobOriginStatistic::nodes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Phloppy\Statistic;
4
5
use Phloppy\Exception;
6
use Phloppy\Job;
7
use Psr\Log\LoggerInterface;
8
use Psr\Log\NullLogger;
9
use SebastianBergmann\RecursionContext\InvalidArgumentException;
10
11
/**
12
 * Collect Statistics of jobs/sec by node.
13
 */
14
class JobOriginStatistic implements NodeStatistic
15
{
16
    /**
17
     * Node Ids
18
     *
19
     * @var \DateTime[]
20
     */
21
    private $lastReceived;
22
23
    /**
24
     * 2-dimensional array storing rates for (queue, nodeId) pairs
25
     * @var string[]
26
     */
27
    private $stats;
28
29
    /**
30
     * @var LoggerInterface
31
     */
32
    private $log;
33
34
    /**
35
     * @var float
36
     */
37
    private $alpha;
38
39
40
    /**
41
     * @param float           $alpha Sensitivity factor.
42
     * @param LoggerInterface $log
0 ignored issues
show
Documentation introduced by
Should the type for parameter $log not be null|LoggerInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
43
     */
44
    function __construct($alpha = 0.9, LoggerInterface $log = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
45
    {
46
        if (!$log) {
47
            $log = new NullLogger();
48
        }
49
50
        if ((float) $alpha < 0.5 || (float) $alpha > 1.0) {
51
            throw new InvalidArgumentException('0.5 < $alpha < 1.0');
52
        }
53
54
        $this->alpha = (float) $alpha;
55
        $this->log = $log;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
56
    }
57
58
59
    /**
60
     * Update jobs by node/sec rt-statistic.
61
     *
62
     * @param Job       $job
63
     *
64
     * @param \DateTime $receivedAt
0 ignored issues
show
Documentation introduced by
Should the type for parameter $receivedAt not be null|\DateTime?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
65
     *
66
     * @return float messages/sec from the given node
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
67
     */
68
    public function update(Job $job, \DateTime $receivedAt = null)
69
    {
70
        $nodeId = $job->getOriginNode();
71
        $queue = $job->getQueue();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
72
73
        if (!$receivedAt) {
74
            $receivedAt = new \DateTime('now');
75
        }
76
77
        if (!isset($this->lastReceived[$queue][$nodeId])) {
78
            $this->lastReceived[$queue][$nodeId] = clone $receivedAt;
79
        }
80
81
        if (!isset($this->stats[$queue])) {
82
            $this->stats[$queue] = [];
83
        }
84
85
        if (!isset($this->stats[$queue][$nodeId])) {
86
            $this->stats[$queue][$nodeId] = 0.;
87
        }
88
89
        $secs = $receivedAt->diff($this->lastReceived[$queue][$nodeId])->s;
90
91
        if ($secs < 0) {
92
            $secs = 0;
93
        }
94
95
        $this->lastReceived[$queue][$nodeId] = clone $receivedAt;
96
        // exp moving average from the last message to now (per sec)
97
        $this->stats[$queue][$nodeId] =
98
            pow($this->alpha, $secs) * $this->stats[$queue][$nodeId] +
99
            (1 - $this->alpha);
100
101
        $this->log->debug('updated value', [
102
            'id' => $nodeId,
103
            'queue' => $queue,
104
            'value' => $this->stats[$nodeId],
105
            'delta' => $secs
106
        ]);
107
108
        return $this->stats[$nodeId];
109
    }
110
111
112
    /**
113
     * Return an ordered list of nodes.
114
     *
115
     * The list is ordered descending by the frequency of Jobs.
116
     *
117
     * @return float[]
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
118
     */
119
    public function nodes($queue)
120
    {
121
        assert(arsort($this->stats[$queue]), true);
122
        return $this->stats[$queue];
123
    }
124
125
126
    /**
127
     * Return information on a specific (queue, node).
128
     *
129
     * If the queue and/or node is not known, no messages have been retrieved from it, so 0. will be returned.
130
     *
131
     * @param string $queue
132
     * @param string $nodeId
133
     *
134
     * @return float msg rate (per sec)
0 ignored issues
show
Documentation introduced by
Should the return type not be string|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
135
     */
136
    public function node($queue, $nodeId)
137
    {
138
        return isset($this->stats[$queue][$nodeId]) ? $this->stats[$queue][$nodeId] : 0.;
139
    }
140
}