From a203ab9388255a6d4ab197babb314082e4590587 Mon Sep 17 00:00:00 2001 From: Ian Torres Date: Wed, 9 Jul 2025 00:01:44 -0400 Subject: [PATCH] STAT implemented. --- src/Connection.php | 3 ++ src/Requests/BaseRequest.php | 15 ++++++ src/Requests/GetRequest.php | 15 ++++++ src/Requests/InfoRequest.php | 15 ++++++ src/Requests/InsertRequest.php | 15 ++++++ src/Requests/ListRequest.php | 15 ++++++ src/Requests/PurgeRequest.php | 15 ++++++ src/Requests/QueryRequest.php | 15 ++++++ src/Requests/SetRequest.php | 15 ++++++ src/Requests/StatRequest.php | 58 ++++++++++++++++++++++ src/Requests/StatsRequest.php | 15 ++++++ src/Requests/UpdateRequest.php | 15 ++++++ src/Responses/GetResponse.php | 15 ++++++ src/Responses/IResponse.php | 15 ++++++ src/Responses/InfoResponse.php | 15 ++++++ src/Responses/ListResponse.php | 15 ++++++ src/Responses/QueryResponse.php | 15 ++++++ src/Responses/Response.php | 15 ++++++ src/Responses/StatResponse.php | 83 ++++++++++++++++++++++++++++++++ src/Responses/StatsResponse.php | 15 ++++++ src/Responses/StatusResponse.php | 15 ++++++ src/Service.php | 16 +++++- tests/ServiceTest.php | 30 ++++++++++++ 23 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 src/Requests/StatRequest.php create mode 100644 src/Responses/StatResponse.php diff --git a/src/Connection.php b/src/Connection.php index 71a3210..0b80776 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -26,6 +26,7 @@ use Throttr\SDK\Responses\InfoResponse; use Throttr\SDK\Responses\ListResponse; use Throttr\SDK\Responses\QueryResponse; +use Throttr\SDK\Responses\StatResponse; use Throttr\SDK\Responses\StatsResponse; use Throttr\SDK\Responses\StatusResponse; @@ -172,12 +173,14 @@ private function processResponses(): void while (!empty($pendingOperations)) { $operation = $pendingOperations[0]; + $response = match ($operation) { RequestType::INSERT, RequestType::UPDATE, RequestType::PURGE, RequestType::SET => StatusResponse::fromBytes($buffer, $this->size), RequestType::QUERY => QueryResponse::fromBytes($buffer, $this->size), RequestType::GET => GetResponse::fromBytes($buffer, $this->size), RequestType::LIST => ListResponse::fromBytes($buffer, $this->size), RequestType::INFO => InfoResponse::fromBytes($buffer, $this->size), + RequestType::STAT => StatResponse::fromBytes($buffer, $this->size), RequestType::STATS => StatsResponse::fromBytes($buffer, $this->size), }; diff --git a/src/Requests/BaseRequest.php b/src/Requests/BaseRequest.php index 9f1da34..2310c3c 100644 --- a/src/Requests/BaseRequest.php +++ b/src/Requests/BaseRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Contracts\ShouldDefineSerialization; diff --git a/src/Requests/GetRequest.php b/src/Requests/GetRequest.php index bfa286d..536afd0 100644 --- a/src/Requests/GetRequest.php +++ b/src/Requests/GetRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/InfoRequest.php b/src/Requests/InfoRequest.php index 9a5147b..357ecf7 100644 --- a/src/Requests/InfoRequest.php +++ b/src/Requests/InfoRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/InsertRequest.php b/src/Requests/InsertRequest.php index 2ec1669..046c5a7 100644 --- a/src/Requests/InsertRequest.php +++ b/src/Requests/InsertRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/ListRequest.php b/src/Requests/ListRequest.php index 0ff5ce0..f3af9db 100644 --- a/src/Requests/ListRequest.php +++ b/src/Requests/ListRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/PurgeRequest.php b/src/Requests/PurgeRequest.php index 1644ff2..bad78ea 100644 --- a/src/Requests/PurgeRequest.php +++ b/src/Requests/PurgeRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/QueryRequest.php b/src/Requests/QueryRequest.php index f921107..71e4214 100644 --- a/src/Requests/QueryRequest.php +++ b/src/Requests/QueryRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/SetRequest.php b/src/Requests/SetRequest.php index 10240c5..1f56b32 100644 --- a/src/Requests/SetRequest.php +++ b/src/Requests/SetRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/StatRequest.php b/src/Requests/StatRequest.php new file mode 100644 index 0000000..51a2901 --- /dev/null +++ b/src/Requests/StatRequest.php @@ -0,0 +1,58 @@ +. + +namespace Throttr\SDK\Requests; + +use Throttr\SDK\Enum\RequestType; +use Throttr\SDK\Enum\ValueSize; + +/** + * Stat request + */ +class StatRequest extends BaseRequest +{ + /** + * Type + * + * @var RequestType + */ + public RequestType $type = RequestType::STAT; + + /** + * Constructor + * + * @param string $key + */ + public function __construct( + public string $key + ) + { + } + + /** + * To bytes + * + * @param ValueSize $size + * @return string + */ + public function toBytes(ValueSize $size): string + { + return pack(static::pack(ValueSize::UINT8), $this->type->value) . + pack(static::pack(ValueSize::UINT8), strlen($this->key)) . + $this->key; + } +} diff --git a/src/Requests/StatsRequest.php b/src/Requests/StatsRequest.php index cbdc604..14cdbd9 100644 --- a/src/Requests/StatsRequest.php +++ b/src/Requests/StatsRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\RequestType; diff --git a/src/Requests/UpdateRequest.php b/src/Requests/UpdateRequest.php index cb091ec..d982b4d 100644 --- a/src/Requests/UpdateRequest.php +++ b/src/Requests/UpdateRequest.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Requests; use Throttr\SDK\Enum\AttributeType; diff --git a/src/Responses/GetResponse.php b/src/Responses/GetResponse.php index e042e4c..5086e29 100644 --- a/src/Responses/GetResponse.php +++ b/src/Responses/GetResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\TTLType; diff --git a/src/Responses/IResponse.php b/src/Responses/IResponse.php index e7c0b93..19e2636 100644 --- a/src/Responses/IResponse.php +++ b/src/Responses/IResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\ValueSize; diff --git a/src/Responses/InfoResponse.php b/src/Responses/InfoResponse.php index 8bd0c95..42c2b15 100644 --- a/src/Responses/InfoResponse.php +++ b/src/Responses/InfoResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\KeyType; diff --git a/src/Responses/ListResponse.php b/src/Responses/ListResponse.php index e404f7f..db8f5d8 100644 --- a/src/Responses/ListResponse.php +++ b/src/Responses/ListResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\KeyType; diff --git a/src/Responses/QueryResponse.php b/src/Responses/QueryResponse.php index 52acd62..6ee1b36 100644 --- a/src/Responses/QueryResponse.php +++ b/src/Responses/QueryResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\TTLType; diff --git a/src/Responses/Response.php b/src/Responses/Response.php index c3069db..36bdcb3 100644 --- a/src/Responses/Response.php +++ b/src/Responses/Response.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; class Response diff --git a/src/Responses/StatResponse.php b/src/Responses/StatResponse.php new file mode 100644 index 0000000..12df19e --- /dev/null +++ b/src/Responses/StatResponse.php @@ -0,0 +1,83 @@ +. + +namespace Throttr\SDK\Responses; + +use Throttr\SDK\Enum\ValueSize; +use Throttr\SDK\Requests\BaseRequest; + +/** + * StatResponse + */ +class StatResponse extends Response implements IResponse { + /** + * Constructor + * + * @param string $data + * @param bool $status + * @param array $attributes + */ + public function __construct(public string $data, public bool $status, public array $attributes) {} + + /** + * From bytes + * + * @param string $data + * @param ValueSize $size + * @return StatResponse|null + */ + public static function fromBytes(string $data, ValueSize $size) : StatResponse|null { + $valueSize = $size->value; + $offset = 0; + + echo bin2hex($data) . "\n"; + + // Less than 1 byte? not enough for status. + if (strlen($data) < 1) return null; + + $status = ord($data[$offset]) === 1; + + $offset++; + + if ($status) { + // Less than offset + 32 bytes? not enough for fields. + if (strlen($data) < $offset + 32) return null; + + $reads_per_minute = unpack(BaseRequest::pack(ValueSize::UINT64), substr($data, $offset, ValueSize::UINT64->value))[1]; + $offset += ValueSize::UINT64->value; + + $writes_per_minute = unpack(BaseRequest::pack(ValueSize::UINT64), substr($data, $offset, ValueSize::UINT64->value))[1]; + $offset += ValueSize::UINT64->value; + + $total_reads = unpack(BaseRequest::pack(ValueSize::UINT64), substr($data, $offset, ValueSize::UINT64->value))[1]; + $offset += ValueSize::UINT64->value; + + $total_writes = unpack(BaseRequest::pack(ValueSize::UINT64), substr($data, $offset, ValueSize::UINT64->value))[1]; + $offset += ValueSize::UINT64->value; + + return new StatResponse($data, true, [ + "reads_per_minute" => $reads_per_minute, + "writes_per_minute" => $writes_per_minute, + "total_reads" => $total_reads, + "total_writes" => $total_writes, + ]); + } + + return new StatResponse($data, false, []); + } +} + diff --git a/src/Responses/StatsResponse.php b/src/Responses/StatsResponse.php index 02cd401..e3bdf0f 100644 --- a/src/Responses/StatsResponse.php +++ b/src/Responses/StatsResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\KeyType; diff --git a/src/Responses/StatusResponse.php b/src/Responses/StatusResponse.php index b2e1ed1..427cb86 100644 --- a/src/Responses/StatusResponse.php +++ b/src/Responses/StatusResponse.php @@ -1,5 +1,20 @@ . + namespace Throttr\SDK\Responses; use Throttr\SDK\Enum\ValueSize; diff --git a/src/Service.php b/src/Service.php index 9c39ab2..59ca9c4 100644 --- a/src/Service.php +++ b/src/Service.php @@ -31,6 +31,7 @@ use Throttr\SDK\Requests\PurgeRequest; use Throttr\SDK\Requests\QueryRequest; use Throttr\SDK\Requests\SetRequest; +use Throttr\SDK\Requests\StatRequest; use Throttr\SDK\Requests\StatsRequest; use Throttr\SDK\Requests\UpdateRequest; use Throttr\SDK\Responses\GetResponse; @@ -38,6 +39,7 @@ use Throttr\SDK\Responses\IResponse; use Throttr\SDK\Responses\ListResponse; use Throttr\SDK\Responses\QueryResponse; +use Throttr\SDK\Responses\StatResponse; use Throttr\SDK\Responses\StatsResponse; use Throttr\SDK\Responses\StatusResponse; @@ -54,7 +56,7 @@ final class Service private array $connections = []; /** - * Round robin index + * Round-robin index * * @var int */ @@ -190,6 +192,18 @@ public function query(string $key): QueryResponse return $this->send([$request])[0]; } + /** + * STAT + * + * @param string $key + * @return StatResponse + */ + public function stat(string $key): StatResponse + { + $request = new StatRequest($key); + return $this->send([$request])[0]; + } + /** * PURGE * diff --git a/tests/ServiceTest.php b/tests/ServiceTest.php index 0679d04..261acaf 100644 --- a/tests/ServiceTest.php +++ b/tests/ServiceTest.php @@ -398,4 +398,34 @@ public function testFragmentedStats() { }); } + public function testStat() { + $this->prepares(function (Service $service) { + $key = 'STAT_KEY'; + $stat = $service->stat($key); + $this->assertFalse($stat->status); + + $service->insert( + key: $key, + ttl: 3, + ttlType: TTLType::SECONDS, + quota: 10, + ); + + $stat = $service->stat($key); + + $this->assertTrue($stat->status); + $this->assertEquals(0, $stat->attributes["reads_per_minute"]); + $this->assertEquals(0, $stat->attributes["writes_per_minute"]); + $this->assertEquals(0, $stat->attributes["total_reads"]); + $this->assertEquals(0, $stat->attributes["total_writes"]); + + $service->purge( + key: $key, + ); + + $stats = $service->stat($key); + $this->assertFalse($stats->status); + }); + } + }