Passed
Push — master ( 71c82d...bff949 )
by xu
01:03 queued 11s
created

Sonyflake::elapsedTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the godruoyi/php-snowflake.
5
 *
6
 * (c) Godruoyi <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled.
9
 */
10
11
namespace Godruoyi\Snowflake;
12
13
class Sonyflake extends Snowflake
14
{
15
    const MAX_TIMESTAMP_LENGTH = 39;
16
17
    const MAX_MACHINEID_LENGTH = 16;
18
19
    const MAX_SEQUENCE_LENGTH = 8;
20
21
    /**
22
     * The machine ID.
23
     *
24
     * @var int
25
     */
26
    protected $machineid;
27
28
    /**
29
     * Build Sonyflake Instance.
30
     *
31
     * @param int $machineid machine ID 0 ~ 65535 (2^16)-1
32
     */
33 8
    public function __construct(int $machineid = 0)
34
    {
35 8
        $maxMachineID = -1 ^ (-1 << self::MAX_MACHINEID_LENGTH);
36
37 8
        $this->machineid = $machineid;
38 8
        if ($this->machineid < 0 || $this->machineid > $maxMachineID) {
39 1
            throw new \InvalidArgumentException("Invalid machine ID, must be between 0 ~ {$maxMachineID}.");
40
        }
41 8
    }
42
43
    /**
44
     * Get Sonyflake id.
45
     *
46
     * @return string
47
     */
48 2
    public function id()
49
    {
50 2
        $elapsedTime = $this->elapsedTime();
51
52 2
        while (($sequence = $this->callResolver($elapsedTime)) > (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH))) {
53
            $elapsedTime2 = $this->elapsedTime();
54
            // Get next timestamp
55
            while ($elapsedTime2 == $elapsedTime) {
56
                usleep(1);
57
                $elapsedTime2 = $this->elapsedTime();
58
            }
59
            $elapsedTime = $elapsedTime2;
60
        }
61
62 2
        $machineidLeftMoveLength = self::MAX_SEQUENCE_LENGTH;
63 2
        $timestampLeftMoveLength = self::MAX_MACHINEID_LENGTH + $machineidLeftMoveLength;
64
65 2
        if ($elapsedTime > (-1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH))) {
66
            // The lifetime (174 years).
67
            throw new \Exception('Exceeding the maximum life cycle of the algorithm.');
68
        }
69
70 2
        return (string) ($elapsedTime << $timestampLeftMoveLength
71 2
            | ($this->machineid << $machineidLeftMoveLength)
72 2
            | ($sequence));
73
    }
74
75
    /**
76
     * Set start time (millisecond).
77
     */
78 2 View Code Duplication
    public function setStartTimeStamp(int $startTime)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
79
    {
80 2
        $elapsedTime = floor(($this->getCurrentMicrotime() - $startTime) / 10) | 0;
81 2
        if ($elapsedTime < 0) {
82
            throw new \Exception('The start time cannot be greater than the current time');
83
        }
84
85 2
        $maxTimeDiff = -1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH);
86 2
        if ($elapsedTime > $maxTimeDiff) {
87 1
            throw new \Exception('Exceeding the maximum life cycle of the algorithm');
88
        }
89
90 1
        $this->startTime = $startTime;
91
92 1
        return $this;
93
    }
94
95
    /**
96
     * Parse snowflake id.
97
     */
98 1
    public function parseId(string $id, $transform = false): array
99
    {
100 1
        $id = decbin($id);
101 1
        $length = self::MAX_SEQUENCE_LENGTH + self::MAX_MACHINEID_LENGTH;
102
103
        $data = [
104 1
            'sequence' => substr($id, -1 * self::MAX_SEQUENCE_LENGTH),
105 1
            'machineid' => substr($id, -1 * $length, self::MAX_MACHINEID_LENGTH),
106 1
            'timestamp' => substr($id, 0, $length),
107
        ];
108
109
        return $transform ? array_map(function ($value) {
110 1
            return bindec($value);
111 1
        }, $data) : $data;
112
    }
113
114
    /**
115
     * The Elapsed Time.
116
     *
117
     * @return int
118
     */
119 2
    private function elapsedTime()
120
    {
121 2
        return floor(($this->getCurrentMicrotime() - $this->getStartTimeStamp()) / 10) | 0;
122
    }
123
}
124