From 46499475eb2eb3bdbf03ec059244bb65ee35a106 Mon Sep 17 00:00:00 2001 From: Yakov Permyakov Date: Tue, 8 Apr 2025 13:26:31 +0300 Subject: [PATCH 1/2] get with prefix --- src/Client.php | 45 +++++++++++++++++++++++++++++++++-------- src/ClientInterface.php | 13 +++++++++++- src/FailoverClient.php | 11 +++++++++- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/Client.php b/src/Client.php index 8879ed6..a3aa261 100644 --- a/src/Client.php +++ b/src/Client.php @@ -29,6 +29,7 @@ use Etcdserverpb\ResponseOp; use Etcdserverpb\TxnRequest; use Etcdserverpb\TxnResponse; +use Generator; use Grpc\ChannelCredentials; use Mvccpb\KeyValue; @@ -129,7 +130,7 @@ public function put(string $key, $value, bool $prevKv = false, int $leaseID = 0, $request->setLease($leaseID); /** @var PutResponse $response */ - list($response, $status) = $client->Put($request, $this->getMetaData(), $this->getOptions())->wait(); + [$response, $status] = $client->Put($request, $this->getMetaData(), $this->getOptions())->wait(); $this->validateStatus($status); if ($prevKv) { @@ -152,7 +153,7 @@ public function get(string $key) $request->setKey($key); /** @var RangeResponse $response */ - list($response, $status) = $client->Range($request, $this->getMetaData(), $this->getOptions())->wait(); + [$response, $status] = $client->Range($request, $this->getMetaData(), $this->getOptions())->wait(); $this->validateStatus($status); $field = $response->getKvs(); @@ -164,6 +165,34 @@ public function get(string $key) return $field[0]->getValue(); } + /** + * Get range of values by key prefix + * + * @param string $prefix + * @return bool|Generator + * @throws InvalidResponseStatusCodeException + */ + public function getWithPrefix(string $prefix): Generator + { + $client = $this->getKvClient(); + + $request = new RangeRequest(); + $request->setKey($prefix); + $request->setRangeEnd($prefix."\xff"); + + /** @var RangeResponse $response */ + [$response, $status] = $client->Range($request, $this->getMetaData(), $this->getOptions())->wait(); + $this->validateStatus($status); + + $field = $response->getKvs(); + + if (count($field) === 0) { + return false; + } + + yield from $field; + } + /** * Delete a key * @@ -179,7 +208,7 @@ public function delete(string $key) $request->setKey($key); /** @var DeleteRangeResponse $response */ - list($response, $status) = $client->DeleteRange($request, $this->getMetaData(), $this->getOptions())->wait(); + [$response, $status] = $client->DeleteRange($request, $this->getMetaData(), $this->getOptions())->wait(); $this->validateStatus($status); if ($response->getDeleted() > 0) { @@ -242,7 +271,7 @@ public function getLeaseID(int $ttl) $leaseRequest->setTTL($ttl); /** @var LeaseGrantResponse $response */ - list($response, $status) = $lease->LeaseGrant($leaseRequest, $this->getMetaData())->wait(); + [$response, $status] = $lease->LeaseGrant($leaseRequest, $this->getMetaData())->wait(); $this->validateStatus($status); return (int)$response->getID(); @@ -260,7 +289,7 @@ public function revokeLeaseID(int $leaseID) $leaseRequest = new LeaseRevokeRequest(); $leaseRequest->setID($leaseID); - list(, $status) = $lease->LeaseRevoke($leaseRequest, $this->getMetaData())->wait(); + [, $status] = $lease->LeaseRevoke($leaseRequest, $this->getMetaData())->wait(); $this->validateStatus($status); } @@ -312,7 +341,7 @@ public function txnRequest(array $requestOperations, ?array $failureOperations, $request->setFailure($failureOperations); /** @var TxnResponse $response */ - list($response, $status) = $client->Txn($request, $this->getMetaData(), $this->getOptions())->wait(); + [$response, $status] = $client->Txn($request, $this->getMetaData(), $this->getOptions())->wait(); $this->validateStatus($status); return $response; @@ -504,7 +533,7 @@ protected function getAuthenticationToken(): string $request->setPassword($this->password); /** @var AuthenticateResponse $response */ - list($response, $status) = $client->Authenticate($request, [], $this->getOptions())->wait(); + [$response, $status] = $client->Authenticate($request, [], $this->getOptions())->wait(); $this->validateStatus($status); $this->token = $response->getToken(); @@ -604,4 +633,4 @@ protected function getFailOperation(string $key, bool $returnNewValueOnFail) return $failOperation; } -} \ No newline at end of file +} diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 52e4b15..47c569a 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -7,6 +7,8 @@ use Etcdserverpb\RequestOp; use Etcdserverpb\TxnResponse; use Exception; +use Generator; +use Mvccpb\KeyValue; /** * Interface ClientInterface @@ -44,6 +46,15 @@ public function put(string $key, $value, bool $prevKv = false, int $leaseID = 0, */ public function get(string $key); + /** + * Get range of values by key prefix + * + * @param string $prefix + * @return bool|Generator + * @throws InvalidResponseStatusCodeException + */ + public function getWithPrefix(string $prefix); + /** * Delete a key * @@ -172,4 +183,4 @@ public function refreshLease(int $leaseID); * ] */ public function getResponses(TxnResponse $txnResponse, ?string $type = null, bool $simpleArray = false): array; -} \ No newline at end of file +} diff --git a/src/FailoverClient.php b/src/FailoverClient.php index d2a4003..236b32a 100644 --- a/src/FailoverClient.php +++ b/src/FailoverClient.php @@ -104,6 +104,15 @@ public function get(string $key) return $this->callClientMethod(__FUNCTION__, false, $key); } + /** + * @inheritDoc + * @throws NoClientAvailableException + */ + public function getWithPrefix(string $prefix) + { + return $this->callClientMethod(__FUNCTION__, false, $prefix); + } + /** * @inheritDoc * @throws NoClientAvailableException @@ -321,4 +330,4 @@ protected function callClientMethod(string $name, bool $isLocalCall, ...$argumen } } } -} \ No newline at end of file +} From a8c8fb8982efe9ed3f16a12b649da0f55362d832 Mon Sep 17 00:00:00 2001 From: Yakov Permyakov Date: Fri, 18 Apr 2025 13:27:19 +0300 Subject: [PATCH 2/2] limited range request --- src/Client.php | 37 ++++++++++++++++++++++++------------- src/ClientInterface.php | 5 +++-- src/FailoverClient.php | 7 +++++-- src/ShardedClient.php | 14 +++++++++++++- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/Client.php b/src/Client.php index a3aa261..9fcfee8 100644 --- a/src/Client.php +++ b/src/Client.php @@ -169,28 +169,39 @@ public function get(string $key) * Get range of values by key prefix * * @param string $prefix - * @return bool|Generator + * @param int $limit + * @return Generator * @throws InvalidResponseStatusCodeException */ - public function getWithPrefix(string $prefix): Generator + public function getWithPrefix(string $prefix, int $limit = 100): Generator { $client = $this->getKvClient(); + $rangeEnd = $prefix."\xff"; - $request = new RangeRequest(); - $request->setKey($prefix); - $request->setRangeEnd($prefix."\xff"); + do{ + $request = (new RangeRequest()) + ->setKey($prefix) + ->setRangeEnd($rangeEnd) + ->setLimit($limit); - /** @var RangeResponse $response */ - [$response, $status] = $client->Range($request, $this->getMetaData(), $this->getOptions())->wait(); - $this->validateStatus($status); + /** @var RangeResponse $response */ + [$response, $status] = $client->Range($request, $this->getMetaData(), $this->getOptions())->wait(); + $this->validateStatus($status); - $field = $response->getKvs(); + $field = $response->getKvs(); + if (count($field) === 0) { + return; + } - if (count($field) === 0) { - return false; - } + foreach ($field as $kv) { + yield $kv; + } - yield from $field; + if(!isset($kv)) { + return; + } + $prefix = $kv->getKey()."\x00"; + }while (true); } /** diff --git a/src/ClientInterface.php b/src/ClientInterface.php index 47c569a..4132ddc 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -50,10 +50,11 @@ public function get(string $key); * Get range of values by key prefix * * @param string $prefix - * @return bool|Generator + * @param int $limit The limit number of keys to be returned in one request (size of page) + * @return Generator * @throws InvalidResponseStatusCodeException */ - public function getWithPrefix(string $prefix); + public function getWithPrefix(string $prefix, int $limit = 100): Generator; /** * Delete a key diff --git a/src/FailoverClient.php b/src/FailoverClient.php index 236b32a..628e1df 100644 --- a/src/FailoverClient.php +++ b/src/FailoverClient.php @@ -10,6 +10,7 @@ use Etcdserverpb\Compare; use Etcdserverpb\RequestOp; use Etcdserverpb\TxnResponse; +use Generator; /** * Class FailoverClient @@ -105,12 +106,14 @@ public function get(string $key) } /** + * @param string $prefix + * @param int $limit * @inheritDoc * @throws NoClientAvailableException */ - public function getWithPrefix(string $prefix) + public function getWithPrefix(string $prefix, int $limit = 100): Generator { - return $this->callClientMethod(__FUNCTION__, false, $prefix); + return $this->callClientMethod(__FUNCTION__, false, $prefix, $limit); } /** diff --git a/src/ShardedClient.php b/src/ShardedClient.php index 426dc45..3bbe6ab 100644 --- a/src/ShardedClient.php +++ b/src/ShardedClient.php @@ -8,6 +8,7 @@ use Etcdserverpb\TxnResponse; use Flexihash\Exception; use Flexihash\Flexihash; +use Generator; /** * Class ShardedClient @@ -114,6 +115,17 @@ public function get(string $key) return $this->getClientFromKey($key)->get($key); } + /** + * @param string $prefix + * @param int $limit + * @inheritDoc + * @throws Exception + */ + public function getWithPrefix(string $prefix, int $limit = 100): Generator + { + return $this->getClientFromKey($prefix)->getWithPrefix($prefix, $limit); + } + /** * @inheritDoc * @throws Exception @@ -233,4 +245,4 @@ public function getResponses(TxnResponse $txnResponse, ?string $type = null, boo { return $this->getRandomClient()->getResponses($txnResponse, $type, $simpleArray); } -} \ No newline at end of file +}