new files
This commit is contained in:
20
pro_v3.5.1/vendor/godruoyi/php-snowflake/.editorconfig
vendored
Normal file
20
pro_v3.5.1/vendor/godruoyi/php-snowflake/.editorconfig
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{vue,js,scss}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
14
pro_v3.5.1/vendor/godruoyi/php-snowflake/CHANGELOG.md
vendored
Normal file
14
pro_v3.5.1/vendor/godruoyi/php-snowflake/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to godruoyi/php-snowflake are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
|
||||
|
||||
## [1.1.0] - 09.04.2021
|
||||
|
||||
### Added
|
||||
|
||||
- [#19](https://github.com/godruoyi/php-snowflake/issues/19): Added support for sonyflake Snowflake algorithm. Supported values are:
|
||||
|
||||
### Changed
|
||||
|
||||
- Add sonyflake support.
|
||||
- [#19](https://github.com/godruoyi/php-snowflake/issues/19): 能否增加索尼雪花算法。
|
||||
21
pro_v3.5.1/vendor/godruoyi/php-snowflake/LICENSE
vendored
Normal file
21
pro_v3.5.1/vendor/godruoyi/php-snowflake/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 godruoyi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
171
pro_v3.5.1/vendor/godruoyi/php-snowflake/README-zh_CN.md
vendored
Normal file
171
pro_v3.5.1/vendor/godruoyi/php-snowflake/README-zh_CN.md
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
<div>
|
||||
<p align="center">
|
||||
<image src="https://www.pngkey.com/png/full/105-1052235_snowflake-png-transparent-background-snowflake-with-clear-background.png" width="250" height="250"></image>
|
||||
</p>
|
||||
<p align="center">An ID Generator for PHP based on Snowflake Algorithm (Twitter announced).</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/godruoyi/php-snowflake/actions/workflows/test.yml">
|
||||
<image src="https://github.com/godruoyi/php-snowflake/actions/workflows/test.yml/badge.svg" alt="build passed"></image>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/godruoyi/php-snowflake">
|
||||
<img src="https://codecov.io/gh/godruoyi/php-snowflake/branch/master/graph/badge.svg?token=7AAOYCJK97"/>
|
||||
</a>
|
||||
<a href="https://github.com/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/license" alt="License"></image>
|
||||
</a>
|
||||
<a href="https://packagist.org/packages/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/v/stable" alt="Packagist Version"></image>
|
||||
</a>
|
||||
<a href="https://github.com/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/downloads" alt="Total Downloads"></image>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## 说明
|
||||
|
||||
雪花算法的 PHP 实现
|
||||
|
||||

|
||||
|
||||
Snowflake 是 Twitter 内部的一个 ID 生算法,可以通过一些简单的规则保证在大规模分布式情况下生成唯一的 ID 号码。其组成为:
|
||||
|
||||
* 第一个 bit 为未使用的符号位。
|
||||
* 第二部分由 41 位的时间戳(毫秒)构成,他的取值是当前时间相对于某一时间的偏移量。
|
||||
* 第三部分和第四部分的 5 个 bit 位表示数据中心和机器ID,其能表示的最大值为 2^5 -1 = 31。
|
||||
* 最后部分由 12 个 bit 组成,其表示每个工作节点**每毫秒**生成的序列号 ID,同一毫秒内最多可生成 2^12 -1 即 4095 个 ID。
|
||||
|
||||
需要注意的是:
|
||||
|
||||
* 在分布式环境中,5 个 bit 位的 datacenter 和 worker 表示最多能部署 31 个数据中心,每个数据中心最多可部署 31 台节点。
|
||||
* 41 位的二进制长度最多能表示 2^41 -1 毫秒即 69 年,所以雪花算法最多能正常使用 69 年,为了能最大限度的使用该算法,你应该为其指定一个开始时间。
|
||||
|
||||
> 由上可知,雪花算法生成的 ID 并不能保证唯一,如当两个不同请求同一时刻进入相同的数据中心的相同节点时,而此时该节点生成的 sequence 又是相同时,就会导致生成的 ID 重复。
|
||||
|
||||
所以要想使用雪花算法生成唯一的 ID,就需要保证同一节点同一毫秒内生成的序列号是唯一的。基于此,我们在 SDK 中集成了多种序列号提供者:
|
||||
|
||||
* RandomSequenceResolver(随机生成)
|
||||
* RedisSequenceResolver (基于 redis psetex 和 incrby 生成)
|
||||
* LaravelSequenceResolver(基于 redis psetex 和 incrby 生成)
|
||||
* SwooleSequenceResolver(基于 swoole_lock 锁)
|
||||
* FileLockResolver(基于 PHP 文件锁)
|
||||
|
||||
> **Warning**
|
||||
> RandomSequenceResolver 序列号提供者在高并发情况下可能会导致生成的 ID 重复,如果你的应用场景中可能会出现高并发的情况,建议使用 RedisSequenceResolver 或者 LaravelSequenceResolver。
|
||||
|
||||
## 要求
|
||||
|
||||
1. PHP >= 7.0
|
||||
2. **[Composer](https://getcomposer.org/)**
|
||||
|
||||
## 安装
|
||||
|
||||
```shell
|
||||
$ composer require godruoyi/php-snowflake -vvv
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
1. 简单使用.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
|
||||
$snowflake->id();
|
||||
// 1537200202186752
|
||||
```
|
||||
|
||||
2. 指定数据中心ID及机器ID.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake($datacenterId, $workerId);
|
||||
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
3. 指定开始时间.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
$snowflake->setStartTimeStamp(strtotime('2019-08-08')*1000);
|
||||
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
## 高级
|
||||
|
||||
1. 在 Laravel 中使用
|
||||
|
||||
因为 SDK 相对简单,我们并没有提供 Laravel 的扩展包,你可通过下面的方式快速集成到 Laravel 中。
|
||||
|
||||
```php
|
||||
// App\Providers\AppServiceProvider
|
||||
|
||||
use Godruoyi\Snowflake\Snowflake;
|
||||
use Godruoyi\Snowflake\LaravelSequenceResolver;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('snowflake', function ($app) {
|
||||
return (new Snowflake())
|
||||
->setStartTimeStamp(strtotime('2019-10-10')*1000)
|
||||
->setSequenceResolver(new LaravelSequenceResolver($app->get('cache.store')));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. 自定义序列号解决器
|
||||
|
||||
你可以通过实现 Godruoyi\Snowflake\SequenceResolver 接口来自定义序列号解决器。
|
||||
|
||||
```php
|
||||
class YourSequence implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
// Just test.
|
||||
return mt_rand(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// usage
|
||||
|
||||
$snowflake->setSequenceResolver(new YourSequence);
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
你也可以直接使用闭包:
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
$snowflake->setSequenceResolver(function ($currentTime) {
|
||||
static $lastTime;
|
||||
static $sequence;
|
||||
|
||||
if ($lastTime == $currentTime) {
|
||||
++$sequence;
|
||||
} else {
|
||||
$sequence = 0;
|
||||
}
|
||||
|
||||
$lastTime = $currentTime;
|
||||
|
||||
return $sequence;
|
||||
})->id();
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
171
pro_v3.5.1/vendor/godruoyi/php-snowflake/README.md
vendored
Normal file
171
pro_v3.5.1/vendor/godruoyi/php-snowflake/README.md
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
<div>
|
||||
<p align="center">
|
||||
<image src="https://www.pngkey.com/png/full/105-1052235_snowflake-png-transparent-background-snowflake-with-clear-background.png" width="250" height="250"></image>
|
||||
</p>
|
||||
<p align="center">An ID Generator for PHP based on Snowflake Algorithm (Twitter announced).</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/godruoyi/php-snowflake/actions/workflows/test.yml">
|
||||
<image src="https://github.com/godruoyi/php-snowflake/actions/workflows/test.yml/badge.svg" alt="build passed"></image>
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/godruoyi/php-snowflake">
|
||||
<img src="https://codecov.io/gh/godruoyi/php-snowflake/branch/master/graph/badge.svg?token=7AAOYCJK97" alt=""/>
|
||||
</a>
|
||||
<a href="https://github.com/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/license" alt="License"></image>
|
||||
</a>
|
||||
<a href="https://packagist.org/packages/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/v/stable" alt="Packagist Version"></image>
|
||||
</a>
|
||||
<a href="https://github.com/godruoyi/php-snowflake">
|
||||
<image src="https://poser.pugx.org/godruoyi/php-snowflake/downloads" alt="Total Downloads"></image>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## Description
|
||||
|
||||
Snowflake algorithm PHP implementation [中文文档](https://github.com/godruoyi/php-snowflake/blob/master/README-zh_CN.md).
|
||||
|
||||

|
||||
|
||||
Snowflake is a network service for generating unique ID numbers at high scale with some simple guarantees.
|
||||
|
||||
* The first bit is unused sign bit.
|
||||
* The second part consists of a 41-bit timestamp (milliseconds) whose value is the offset of the current time relative to a certain time.
|
||||
* The 5 bits of the third and fourth parts represent data center and worker, and max value is 2^5 -1 = 31.
|
||||
* The last part consists of 12 bits, its means the length of the serial number generated per millisecond per working node, a maximum of 2^12 -1 = 4095 IDs can be generated in the same millisecond.
|
||||
* In a distributed environment, five-bit datacenter and worker mean that can deploy 31 datacenters, and each datacenter can deploy up to 31 nodes.
|
||||
* The binary length of 41 bits is at most 2^41 -1 millisecond = 69 years. So the snowflake algorithm can be used for up to 69 years, In order to maximize the use of the algorithm, you should specify a start time for it.
|
||||
|
||||
> You must know, The ID generated by the snowflake algorithm is not guaranteed to be unique.
|
||||
> For example, when two different requests enter the same node of the same data center at the same time, and the sequence generated by the node is the same, the generated ID will be duplicated.
|
||||
|
||||
So if you want to use the snowflake algorithm to generate unique ID, You must ensure: The sequence-number generated in the same millisecond of the same node is unique.
|
||||
Based on this, we created this package and integrated multiple sequence-number providers into it.
|
||||
|
||||
* RandomSequenceResolver (Random)
|
||||
* RedisSequenceResolver (based on redis psetex and incrby)
|
||||
* LaravelSequenceResolver (based on redis psetex and incrby)
|
||||
* SwooleSequenceResolver (based on swoole_lock)
|
||||
* FileLockResolver(PHP file lock `fopen/flock`)
|
||||
|
||||
Each provider only needs to ensure that the serial number generated in the same millisecond is different. You can get a unique ID.
|
||||
|
||||
> **Warning**
|
||||
> The RandomSequenceResolver does not guarantee that the generated IDs are unique, If you want to generate a unique ID, please use another resolver instead.
|
||||
|
||||
## Requirement
|
||||
|
||||
1. PHP >= 7.2
|
||||
2. **[Composer](https://getcomposer.org/)**
|
||||
|
||||
## Installation
|
||||
|
||||
```shell
|
||||
$ composer require godruoyi/php-snowflake -vvv
|
||||
```
|
||||
|
||||
## Useage
|
||||
|
||||
1. simple to use.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
|
||||
$snowflake->id();
|
||||
// 1537200202186752
|
||||
```
|
||||
|
||||
2. Specify the data center ID and machine ID.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake($datacenterId, $workerId);
|
||||
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
3. Specify start time.
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
$snowflake->setStartTimeStamp(strtotime('2019-09-09')*1000); // millisecond
|
||||
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
1. Used in Laravel.
|
||||
|
||||
Because the SDK is relatively simple, we don't provide an extension for Laravel. You can quickly integrate it into Laravel in the following way.
|
||||
|
||||
```php
|
||||
// App\Providers\AppServiceProvider
|
||||
|
||||
use Godruoyi\Snowflake\Snowflake;
|
||||
use Godruoyi\Snowflake\LaravelSequenceResolver;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('snowflake', function ($app) {
|
||||
return (new Snowflake())
|
||||
->setStartTimeStamp(strtotime('2019-10-10')*1000)
|
||||
->setSequenceResolver(new LaravelSequenceResolver($app->get('cache.store')));
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Custom
|
||||
|
||||
You can customize the sequence-number resolver by implementing the Godruoyi\Snowflake\SequenceResolver interface.
|
||||
|
||||
```php
|
||||
class YourSequence implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentMillisecond)
|
||||
{
|
||||
// Just test.
|
||||
return mt_rand(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// usage
|
||||
|
||||
$snowflake->setSequenceResolver(new YourSequence);
|
||||
$snowflake->id();
|
||||
```
|
||||
|
||||
And you can use closure:
|
||||
|
||||
```php
|
||||
$snowflake = new \Godruoyi\Snowflake\Snowflake;
|
||||
$snowflake->setSequenceResolver(function ($currentMillisecond) {
|
||||
static $lastTime;
|
||||
static $sequence;
|
||||
|
||||
if ($lastTime == $currentMillisecond) {
|
||||
++$sequence;
|
||||
} else {
|
||||
$sequence = 0;
|
||||
}
|
||||
|
||||
$lastTime = $currentMillisecond;
|
||||
|
||||
return $sequence;
|
||||
})->id();
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
35
pro_v3.5.1/vendor/godruoyi/php-snowflake/composer.json
vendored
Normal file
35
pro_v3.5.1/vendor/godruoyi/php-snowflake/composer.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "godruoyi/php-snowflake",
|
||||
"description": "An ID Generator for PHP based on Snowflake Algorithm (Twitter announced).",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"unique id",
|
||||
"snowflake algorithm",
|
||||
"php snowflake",
|
||||
"laravel snowflake",
|
||||
"order id",
|
||||
"unique order id",
|
||||
"php unique id"
|
||||
],
|
||||
"homepage": "https://github.com/godruoyi/php-snowflake",
|
||||
"authors": [{
|
||||
"name": "Godruoyi",
|
||||
"email": "g@godruoyi.com"
|
||||
}],
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~7|^8|^9"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Godruoyi\\Snowflake\\": "src"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
pro_v3.5.1/vendor/godruoyi/php-snowflake/pint.json
vendored
Normal file
8
pro_v3.5.1/vendor/godruoyi/php-snowflake/pint.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"rules": {
|
||||
"header_comment": {
|
||||
"header": "This file is part of the godruoyi/php-snowflake.\n \n(c) Godruoyi <g@godruoyi.com> \n \nThis source file is subject to the MIT license that is bundled."
|
||||
},
|
||||
"no_superfluous_phpdoc_tags": false
|
||||
}
|
||||
}
|
||||
297
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/FileLockResolver.php
vendored
Normal file
297
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/FileLockResolver.php
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
use Exception;
|
||||
|
||||
class FileLockResolver implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* We should always use exclusive lock to avoid the problem of concurrent access.
|
||||
*/
|
||||
public const FlockLockOperation = LOCK_EX;
|
||||
|
||||
public const FileOpenMode = 'r+';
|
||||
|
||||
/**
|
||||
* For each lock file, we save 6,000 items, It can contain data generated within 10 minutes,
|
||||
* we believe is sufficient for the snowflake algorithm.
|
||||
*
|
||||
* 10m = 600s = 6000 ms
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public static $maxItems = 6000;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public static $shardCount = 32;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $lockFileDir;
|
||||
|
||||
/**
|
||||
* @param string|null $lockFileDir
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(string $lockFileDir = null)
|
||||
{
|
||||
$this->lockFileDir = $this->preparePath($lockFileDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws Exception when can not open lock file
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
$filePath = $this->createShardLockFile($this->getShardLockIndex($currentTime));
|
||||
|
||||
return $this->getSequence($filePath, $currentTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next sequence. move lock/unlock in the same method to avoid lock file not release, this
|
||||
* will be more friendly to test.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $currentTime
|
||||
* @return int
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getSequence(string $filePath, int $currentTime): int
|
||||
{
|
||||
$f = null;
|
||||
|
||||
if (! file_exists($filePath)) {
|
||||
throw new Exception(sprintf('the lock file %s not exists', $filePath));
|
||||
}
|
||||
|
||||
try {
|
||||
$f = fopen($filePath, static::FileOpenMode);
|
||||
|
||||
// we always use exclusive lock to avoid the problem of concurrent access.
|
||||
// so we don't need to check the return value of flock.
|
||||
flock($f, static::FlockLockOperation);
|
||||
} catch (\Throwable $e) {
|
||||
$this->unlock($f);
|
||||
|
||||
throw new Exception(sprintf('can not open/lock this file %s', $filePath), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
// We may get this error if the file contains invalid json, when you get this error,
|
||||
// may you can try to delete the invalid lock file directly.
|
||||
if (is_null($contents = $this->getContents($f))) {
|
||||
$this->unlock($f);
|
||||
|
||||
throw new Exception(sprintf('file %s is not a valid lock file.', $filePath));
|
||||
}
|
||||
|
||||
$this->updateContents($contents = $this->incrementSequenceWithSpecifyTime(
|
||||
$this->cleanOldSequences($contents), $currentTime
|
||||
), $f);
|
||||
|
||||
$this->unlock($f);
|
||||
|
||||
return $contents[$currentTime];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock and close file.
|
||||
*
|
||||
* @param $f
|
||||
* @return void
|
||||
*/
|
||||
protected function unlock($f)
|
||||
{
|
||||
if (is_resource($f)) {
|
||||
flock($f, LOCK_UN);
|
||||
fclose($f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $contents
|
||||
* @param $f
|
||||
* @return bool
|
||||
*/
|
||||
public function updateContents(array $contents, $f): bool
|
||||
{
|
||||
return ftruncate($f, 0) && rewind($f)
|
||||
&& (fwrite($f, serialize($contents)) !== false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment sequence with specify time. if current time is not set in the lock file
|
||||
* set it to 1, otherwise increment it.
|
||||
*
|
||||
* @param array $contents
|
||||
* @param int $currentTime
|
||||
* @return array
|
||||
*/
|
||||
public function incrementSequenceWithSpecifyTime(array $contents, int $currentTime): array
|
||||
{
|
||||
$contents[$currentTime] = isset($contents[$currentTime]) ? $contents[$currentTime] + 1 : 1;
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the old content, we only save the data generated within 10 minutes.
|
||||
*
|
||||
* @param array $contents
|
||||
* @return array
|
||||
*/
|
||||
public function cleanOldSequences(array $contents): array
|
||||
{
|
||||
ksort($contents); // sort by timestamp
|
||||
|
||||
if (count($contents) > static::$maxItems) {
|
||||
$contents = array_slice($contents, -static::$maxItems, null, true);
|
||||
}
|
||||
|
||||
return $contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all lock files, we only delete the file that name is match the pattern.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanAllLocksFile()
|
||||
{
|
||||
$files = glob($this->lockFileDir.'/*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file) && preg_match('/snowflake-(\d+)\.lock$/', $file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource contents, If the contents are invalid json, return null.
|
||||
*
|
||||
* @param $f resource
|
||||
* @return array|null
|
||||
*/
|
||||
public function getContents($f): ?array
|
||||
{
|
||||
$content = '';
|
||||
|
||||
while (! feof($f)) {
|
||||
$content .= fread($f, 1024);
|
||||
}
|
||||
|
||||
$content = trim($content);
|
||||
|
||||
if (empty($content)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
if (is_array($data = unserialize($content))) {
|
||||
return $data;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
*
|
||||
* @param string $str
|
||||
* @return float
|
||||
*/
|
||||
public function fnv(string $str): float
|
||||
{
|
||||
$hash = 2166136261;
|
||||
|
||||
for ($i = 0; $i < strlen($str); $i++) {
|
||||
$hash ^= ord($str[$i]);
|
||||
$hash *= 0x01000193;
|
||||
$hash &= 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shard lock file index.
|
||||
*
|
||||
* @param int $currentTime
|
||||
* @return int
|
||||
*/
|
||||
public function getShardLockIndex(int $currentTime): int
|
||||
{
|
||||
return $this->fnv($currentTime) % self::$shardCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check path is exists and writable.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function preparePath(?string $lockFileDir): string
|
||||
{
|
||||
if (empty($lockFileDir)) {
|
||||
$lockFileDir = dirname(__DIR__).'/.locks/';
|
||||
}
|
||||
|
||||
if (! is_dir($lockFileDir)) {
|
||||
throw new Exception("{$lockFileDir} is not a directory.");
|
||||
}
|
||||
|
||||
if (! is_writable($lockFileDir)) {
|
||||
throw new Exception("{$lockFileDir} is not writable.");
|
||||
}
|
||||
|
||||
return $lockFileDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate shard lock file.
|
||||
*
|
||||
* @param int $index
|
||||
* @return string
|
||||
*/
|
||||
protected function createShardLockFile(int $index): string
|
||||
{
|
||||
$path = $this->filePath($index);
|
||||
|
||||
if (file_exists($path)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
touch($path);
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format lock file path with shard index.
|
||||
*
|
||||
* @param int $index
|
||||
* @return string
|
||||
*/
|
||||
protected function filePath(int $index): string
|
||||
{
|
||||
return sprintf('%s%ssnowflake-%s.lock', rtrim($this->lockFileDir, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $index);
|
||||
}
|
||||
}
|
||||
62
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/LaravelSequenceResolver.php
vendored
Normal file
62
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/LaravelSequenceResolver.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
use Illuminate\Contracts\Cache\Repository;
|
||||
|
||||
class LaravelSequenceResolver implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* The laravel cache instance.
|
||||
*
|
||||
* @var Repository
|
||||
*/
|
||||
protected $cache;
|
||||
|
||||
/**
|
||||
* The cache prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Init resolve instance, must connectioned.
|
||||
*/
|
||||
public function __construct(Repository $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
$key = $this->prefix.$currentTime;
|
||||
|
||||
if ($this->cache->add($key, 1, 10)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $this->cache->increment($key, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache prefix.
|
||||
*/
|
||||
public function setCachePrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
61
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/RandomSequenceResolver.php
vendored
Normal file
61
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/RandomSequenceResolver.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
class RandomSequenceResolver implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* The last timestamp.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
protected $lastTimeStamp = -1;
|
||||
|
||||
/**
|
||||
* The sequence.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $sequence = 0;
|
||||
|
||||
/**
|
||||
* Max sequence number in one ms.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $maxSequence = Snowflake::MAX_SEQUENCE_SIZE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
if ($this->lastTimeStamp === $currentTime) {
|
||||
$this->sequence++;
|
||||
$this->lastTimeStamp = $currentTime;
|
||||
|
||||
return $this->sequence;
|
||||
}
|
||||
|
||||
$this->sequence = mt_rand(0, $this->maxSequence);
|
||||
$this->lastTimeStamp = $currentTime;
|
||||
|
||||
return $this->sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $maxSequence
|
||||
*/
|
||||
public function setMaxSequence(int $maxSequence): void
|
||||
{
|
||||
$this->maxSequence = $maxSequence;
|
||||
}
|
||||
}
|
||||
72
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/RedisSequenceResolver.php
vendored
Normal file
72
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/RedisSequenceResolver.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
use Redis;
|
||||
use RedisException;
|
||||
|
||||
class RedisSequenceResolver implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* The redis client instance.
|
||||
*
|
||||
* @var Redis
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
/**
|
||||
* The cache prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* Init resolve instance, must connectioned.
|
||||
*/
|
||||
public function __construct(Redis $redis)
|
||||
{
|
||||
if ($redis->ping()) {
|
||||
$this->redis = $redis;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RedisException('Redis server went away');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
$lua = <<<'LUA'
|
||||
if redis.call('set', KEYS[1], ARGV[1], "EX", ARGV[2], "NX") then
|
||||
return 0
|
||||
else
|
||||
return redis.call('incr', KEYS[1])
|
||||
end
|
||||
LUA;
|
||||
|
||||
// 10 seconds
|
||||
return $this->redis->eval($lua, [$this->prefix.$currentTime, '0', '10'], 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache prefix.
|
||||
*/
|
||||
public function setCachePrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
22
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/SequenceResolver.php
vendored
Normal file
22
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/SequenceResolver.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
interface SequenceResolver
|
||||
{
|
||||
/**
|
||||
* The snowflake.
|
||||
*
|
||||
* @param int|string $currentTime current timestamp: milliseconds
|
||||
* @return int
|
||||
*/
|
||||
public function sequence(int $currentTime);
|
||||
}
|
||||
237
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/Snowflake.php
vendored
Normal file
237
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/Snowflake.php
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
use Exception;
|
||||
|
||||
class Snowflake
|
||||
{
|
||||
public const MAX_TIMESTAMP_LENGTH = 41;
|
||||
|
||||
public const MAX_DATACENTER_LENGTH = 5;
|
||||
|
||||
public const MAX_WORKID_LENGTH = 5;
|
||||
|
||||
public const MAX_SEQUENCE_LENGTH = 12;
|
||||
|
||||
public const MAX_SEQUENCE_SIZE = (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH));
|
||||
|
||||
public const MAX_FIRST_LENGTH = 1;
|
||||
|
||||
/**
|
||||
* The data center id.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $datacenter;
|
||||
|
||||
/**
|
||||
* The worker id.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $workerid;
|
||||
|
||||
/**
|
||||
* The Sequence Resolver instance.
|
||||
*
|
||||
* @var null|SequenceResolver
|
||||
*/
|
||||
protected $sequence;
|
||||
|
||||
/**
|
||||
* The start timestamp.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $startTime;
|
||||
|
||||
/**
|
||||
* Default sequence resolver.
|
||||
*
|
||||
* @var null|SequenceResolver
|
||||
*/
|
||||
protected $defaultSequenceResolver;
|
||||
|
||||
/**
|
||||
* Build Snowflake Instance.
|
||||
*
|
||||
* @param int|null $datacenter
|
||||
* @param int|null $workerid
|
||||
*/
|
||||
public function __construct(int $datacenter = null, int $workerid = null)
|
||||
{
|
||||
$maxDataCenter = -1 ^ (-1 << self::MAX_DATACENTER_LENGTH);
|
||||
$maxWorkId = -1 ^ (-1 << self::MAX_WORKID_LENGTH);
|
||||
|
||||
// If not set datacenter or workid, we will set a default value to use.
|
||||
$this->datacenter = $datacenter > $maxDataCenter || $datacenter < 0 ? mt_rand(0, 31) : $datacenter;
|
||||
$this->workerid = $workerid > $maxWorkId || $workerid < 0 ? mt_rand(0, 31) : $workerid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get snowflake id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function id()
|
||||
{
|
||||
$currentTime = $this->getCurrentMillisecond();
|
||||
while (($sequence = $this->callResolver($currentTime)) > (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH))) {
|
||||
usleep(1);
|
||||
$currentTime = $this->getCurrentMillisecond();
|
||||
}
|
||||
|
||||
$workerLeftMoveLength = self::MAX_SEQUENCE_LENGTH;
|
||||
$datacenterLeftMoveLength = self::MAX_WORKID_LENGTH + $workerLeftMoveLength;
|
||||
$timestampLeftMoveLength = self::MAX_DATACENTER_LENGTH + $datacenterLeftMoveLength;
|
||||
|
||||
return (string) ((($currentTime - $this->getStartTimeStamp()) << $timestampLeftMoveLength)
|
||||
| ($this->datacenter << $datacenterLeftMoveLength)
|
||||
| ($this->workerid << $workerLeftMoveLength)
|
||||
| ($sequence));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse snowflake id.
|
||||
*/
|
||||
public function parseId(string $id, bool $transform = false): array
|
||||
{
|
||||
$id = decbin($id);
|
||||
|
||||
$data = [
|
||||
'timestamp' => substr($id, 0, -22),
|
||||
'sequence' => substr($id, -12),
|
||||
'workerid' => substr($id, -17, 5),
|
||||
'datacenter' => substr($id, -22, 5),
|
||||
];
|
||||
|
||||
return $transform ? array_map(function ($value) {
|
||||
return bindec($value);
|
||||
}, $data) : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current millisecond time.
|
||||
*
|
||||
* @deprecated the method name is wrong, use getCurrentMillisecond instead, will be removed in next major version.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrentMicrotime()
|
||||
{
|
||||
return floor(microtime(true) * 1000) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current millisecond time.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getCurrentMillisecond(): int
|
||||
{
|
||||
return floor(microtime(true) * 1000) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start time (millisecond).
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setStartTimeStamp(int $millisecond)
|
||||
{
|
||||
$missTime = $this->getCurrentMillisecond() - $millisecond;
|
||||
|
||||
if ($missTime < 0) {
|
||||
throw new Exception('The start time cannot be greater than the current time');
|
||||
}
|
||||
|
||||
$maxTimeDiff = -1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH);
|
||||
|
||||
if ($missTime > $maxTimeDiff) {
|
||||
throw new Exception(sprintf('The current microtime - starttime is not allowed to exceed -1 ^ (-1 << %d), You can reset the start time to fix this', self::MAX_TIMESTAMP_LENGTH));
|
||||
}
|
||||
|
||||
$this->startTime = $millisecond;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get start timestamp (millisecond), If not set default to 2019-08-08 08:08:08.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStartTimeStamp()
|
||||
{
|
||||
if (! is_null($this->startTime)) {
|
||||
return $this->startTime;
|
||||
}
|
||||
|
||||
// We set a default start time if you not set.
|
||||
$defaultTime = '2019-08-08 08:08:08';
|
||||
|
||||
return strtotime($defaultTime) * 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Sequence Resolver.
|
||||
*
|
||||
* @param callable|SequenceResolver $sequence
|
||||
*/
|
||||
public function setSequenceResolver($sequence)
|
||||
{
|
||||
$this->sequence = $sequence;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sequence Resolver.
|
||||
*
|
||||
* @return SequenceResolver|null
|
||||
*/
|
||||
public function getSequenceResolver()
|
||||
{
|
||||
return $this->sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Default Sequence Resolver.
|
||||
*
|
||||
* @return SequenceResolver
|
||||
*/
|
||||
public function getDefaultSequenceResolver(): SequenceResolver
|
||||
{
|
||||
return $this->defaultSequenceResolver ?: $this->defaultSequenceResolver = new RandomSequenceResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call resolver.
|
||||
*
|
||||
* @param mixed $currentTime
|
||||
* @return int
|
||||
*/
|
||||
protected function callResolver($currentTime)
|
||||
{
|
||||
$resolver = $this->getSequenceResolver();
|
||||
|
||||
if (is_callable($resolver)) {
|
||||
return $resolver($currentTime);
|
||||
}
|
||||
|
||||
return ! ($resolver instanceof SequenceResolver)
|
||||
? $this->getDefaultSequenceResolver()->sequence($currentTime)
|
||||
: $resolver->sequence($currentTime);
|
||||
}
|
||||
}
|
||||
152
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/Sonyflake.php
vendored
Normal file
152
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/Sonyflake.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
use Exception;
|
||||
|
||||
class Sonyflake extends Snowflake
|
||||
{
|
||||
const MAX_TIMESTAMP_LENGTH = 39;
|
||||
|
||||
const MAX_MACHINEID_LENGTH = 16;
|
||||
|
||||
const MAX_SEQUENCE_LENGTH = 8;
|
||||
|
||||
public const MAX_SEQUENCE_SIZE = (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH));
|
||||
|
||||
/**
|
||||
* The machine ID.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $machineid;
|
||||
|
||||
/**
|
||||
* Build Sonyflake Instance.
|
||||
*
|
||||
* @param int $machineid machine ID 0 ~ 65535 (2^16)-1
|
||||
*/
|
||||
public function __construct(int $machineid = 0)
|
||||
{
|
||||
$maxMachineID = -1 ^ (-1 << self::MAX_MACHINEID_LENGTH);
|
||||
|
||||
$this->machineid = $machineid;
|
||||
if ($this->machineid < 0 || $this->machineid > $maxMachineID) {
|
||||
throw new \InvalidArgumentException("Invalid machine ID, must be between 0 ~ {$maxMachineID}.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Sonyflake id.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function id()
|
||||
{
|
||||
$elapsedTime = $this->elapsedTime();
|
||||
|
||||
while (($sequence = $this->callResolver($elapsedTime)) > (-1 ^ (-1 << self::MAX_SEQUENCE_LENGTH))) {
|
||||
$nextMillisecond = $this->elapsedTime();
|
||||
while ($nextMillisecond == $elapsedTime) {
|
||||
usleep(1);
|
||||
$nextMillisecond = $this->elapsedTime();
|
||||
}
|
||||
$elapsedTime = $nextMillisecond;
|
||||
}
|
||||
|
||||
$this->ensureEffectiveRuntime($elapsedTime);
|
||||
|
||||
return (string) ($elapsedTime << (self::MAX_MACHINEID_LENGTH + self::MAX_SEQUENCE_LENGTH)
|
||||
| ($this->machineid << self::MAX_SEQUENCE_LENGTH)
|
||||
| ($sequence));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start time (millisecond).
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setStartTimeStamp(int $millisecond)
|
||||
{
|
||||
$elapsedTime = floor(($this->getCurrentMillisecond() - $millisecond) / 10) | 0;
|
||||
if ($elapsedTime < 0) {
|
||||
throw new Exception('The start time cannot be greater than the current time');
|
||||
}
|
||||
|
||||
$this->ensureEffectiveRuntime($elapsedTime);
|
||||
|
||||
$this->startTime = $millisecond;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse snowflake id.
|
||||
*/
|
||||
public function parseId(string $id, $transform = false): array
|
||||
{
|
||||
$id = decbin($id);
|
||||
$length = self::MAX_SEQUENCE_LENGTH + self::MAX_MACHINEID_LENGTH;
|
||||
|
||||
$data = [
|
||||
'sequence' => substr($id, -1 * self::MAX_SEQUENCE_LENGTH),
|
||||
'machineid' => substr($id, -1 * $length, self::MAX_MACHINEID_LENGTH),
|
||||
'timestamp' => substr($id, 0, strlen($id) - $length),
|
||||
];
|
||||
|
||||
return $transform ? array_map(function ($value) {
|
||||
return bindec($value);
|
||||
}, $data) : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current timestamp.
|
||||
*/
|
||||
public function getDefaultSequenceResolver(): SequenceResolver
|
||||
{
|
||||
if ($this->defaultSequenceResolver) {
|
||||
return $this->defaultSequenceResolver;
|
||||
}
|
||||
|
||||
$resolver = new RandomSequenceResolver();
|
||||
$resolver->setMaxSequence(self::MAX_SEQUENCE_SIZE);
|
||||
|
||||
return $this->defaultSequenceResolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Elapsed Time, unit: 10millisecond.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function elapsedTime(): int
|
||||
{
|
||||
return floor(($this->getCurrentMillisecond() - $this->getStartTimeStamp()) / 10) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure it's an effective runtime
|
||||
*
|
||||
* @param int $elapsedTime unit: 10millisecond
|
||||
* @return void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function ensureEffectiveRuntime(int $elapsedTime): void
|
||||
{
|
||||
$maxRunTime = -1 ^ (-1 << self::MAX_TIMESTAMP_LENGTH);
|
||||
if ($elapsedTime > $maxRunTime) {
|
||||
throw new Exception('Exceeding the maximum life cycle of the algorithm');
|
||||
}
|
||||
}
|
||||
}
|
||||
89
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/SwooleSequenceResolver.php
vendored
Normal file
89
pro_v3.5.1/vendor/godruoyi/php-snowflake/src/SwooleSequenceResolver.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the godruoyi/php-snowflake.
|
||||
*
|
||||
* (c) Godruoyi <g@godruoyi.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled.
|
||||
*/
|
||||
|
||||
namespace Godruoyi\Snowflake;
|
||||
|
||||
class SwooleSequenceResolver implements SequenceResolver
|
||||
{
|
||||
/**
|
||||
* The las ttimestamp.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
protected $lastTimeStamp = -1;
|
||||
|
||||
/**
|
||||
* The sequence.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $sequence = 0;
|
||||
|
||||
/**
|
||||
* The swoole lock.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $lock;
|
||||
|
||||
/**
|
||||
* The cycle count.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $count = 0;
|
||||
|
||||
/**
|
||||
* Init swoole lock.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->lock = new \Swoole\Lock(SWOOLE_MUTEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sequence(int $currentTime)
|
||||
{
|
||||
// If swoole lock failure,we will return a big number, and recall this method when next millisecond.
|
||||
if (! $this->lock->trylock()) {
|
||||
if ($this->count >= 10) {
|
||||
throw new \Exception('Swoole lock failure, Unable to get the program lock after many attempts.');
|
||||
}
|
||||
|
||||
$this->count++;
|
||||
|
||||
// return a big number
|
||||
return 999999;
|
||||
}
|
||||
|
||||
if ($this->lastTimeStamp === $currentTime) {
|
||||
$this->sequence++;
|
||||
} else {
|
||||
$this->sequence = 0;
|
||||
}
|
||||
|
||||
$this->lastTimeStamp = $currentTime;
|
||||
|
||||
$this->lock->unlock();
|
||||
|
||||
return $this->sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Swoole\Lock $lock
|
||||
* @return void
|
||||
*/
|
||||
public function resetLock(\Swoole\Lock $lock)
|
||||
{
|
||||
$this->lock = $lock;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user