Skip to content

Commit 656c019

Browse files
authored
Merge pull request #1 from 007hacky007/if-custom-compare
Custom compare support for the If methods
2 parents c96bcf9 + 6decc1d commit 656c019

File tree

4 files changed

+266
-70
lines changed

4 files changed

+266
-70
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ $client = new Aternos\Etcd\Client("localhost:2379", "username", "password");
4040
$client->put("key", "value");
4141
$client->get("key");
4242
$client->delete("key");
43-
$client->putIf("key", "newValue", "expectedPreviousValue");
44-
$client->deleteIf("key", "expectedPreviousValue");
43+
$client->putIf("key", "newValue", "valueToCompareWith");
44+
$client->deleteIf("key", "3");
4545
```
4646

4747
#### Sharded client

src/Client.php

Lines changed: 154 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -191,42 +191,41 @@ public function delete(string $key)
191191
* Put $value if $key value matches $previousValue otherwise $returnNewValueOnFail
192192
*
193193
* @param string $key
194-
* @param mixed $value The new value to set
195-
* @param mixed $previousValue The previous value to compare against
194+
* @param string $value The new value to set
195+
* @param bool|string $compareValue The previous value to compare against
196196
* @param bool $returnNewValueOnFail
197197
* @return bool|string
198198
* @throws InvalidResponseStatusCodeException
199+
* @throws \Exception
199200
*/
200-
public function putIf(string $key, $value, $previousValue, bool $returnNewValueOnFail = false)
201+
public function putIf(string $key, string $value, $compareValue, bool $returnNewValueOnFail = false)
201202
{
202-
$request = new PutRequest();
203-
$request->setKey($key);
204-
$request->setValue($value);
205-
206-
$operation = new RequestOp();
207-
$operation->setRequestPut($request);
203+
$operation = $this->getPutOperation($key, $value);
204+
$compare = $this->getCompareForIf($key, $compareValue);
205+
$failOperation = $this->getFailOperation($key, $returnNewValueOnFail);
208206

209-
return $this->requestIf($key, $previousValue, $operation, $returnNewValueOnFail);
207+
$response = $this->txnRequest($key, [$operation], $failOperation, [$compare]);
208+
return $this->getIfResponse($returnNewValueOnFail, $response);
210209
}
211210

212211
/**
213212
* Delete if $key value matches $previous value otherwise $returnNewValueOnFail
214213
*
215214
* @param string $key
216-
* @param $previousValue
215+
* @param bool|string $compareValue The previous value to compare against
217216
* @param bool $returnNewValueOnFail
218217
* @return bool|string
219218
* @throws InvalidResponseStatusCodeException
219+
* @throws \Exception
220220
*/
221-
public function deleteIf(string $key, $previousValue, bool $returnNewValueOnFail = false)
221+
public function deleteIf(string $key, $compareValue, bool $returnNewValueOnFail = false)
222222
{
223-
$request = new DeleteRangeRequest();
224-
$request->setKey($key);
223+
$operation = $this->getDeleteOperation($key);
224+
$compare = $this->getCompareForIf($key, $compareValue);
225+
$failOperation = $this->getFailOperation($key, $returnNewValueOnFail);
225226

226-
$operation = new RequestOp();
227-
$operation->setRequestDeleteRange($request);
228-
229-
return $this->requestIf($key, $previousValue, $operation, $returnNewValueOnFail);
227+
$response = $this->txnRequest($key, [$operation], $failOperation, [$compare]);
228+
return $this->getIfResponse($returnNewValueOnFail, $response);
230229
}
231230

232231
/**
@@ -295,62 +294,103 @@ public function refreshLease(int $leaseID)
295294
* Execute $requestOperation if $key value matches $previous otherwise $returnNewValueOnFail
296295
*
297296
* @param string $key
298-
* @param $previousValue
299-
* @param RequestOp $requestOperation
300-
* @param bool $returnNewValueOnFail
301-
* @return bool|string
297+
* @param array $requestOperations operations to perform on success, array of RequestOp objects
298+
* @param array|null $failureOperations operations to perform on failure, array of RequestOp objects
299+
* @param array $compare array of Compare objects
300+
* @return TxnResponse
302301
* @throws InvalidResponseStatusCodeException
303302
*/
304-
protected function requestIf(string $key, $previousValue, RequestOp $requestOperation, bool $returnNewValueOnFail = false)
303+
public function txnRequest(string $key, array $requestOperations, ?array $failureOperations, array $compare): TxnResponse
305304
{
306305
$client = $this->getKvClient();
307306

308-
$compare = new Compare();
309-
$compare->setKey($key);
310-
311-
if ($previousValue === false) {
312-
$compare->setValue("0");
313-
$compare->setResult(CompareResult::EQUAL);
314-
$compare->setTarget(CompareTarget::VERSION);
315-
} else {
316-
$compare->setValue($previousValue);
317-
$compare->setResult(CompareResult::EQUAL);
318-
$compare->setTarget(CompareTarget::VALUE);
319-
}
320-
321307
$request = new TxnRequest();
322-
$request->setCompare([$compare]);
323-
$request->setSuccess([$requestOperation]);
324-
325-
if ($returnNewValueOnFail) {
326-
$getRequest = new RangeRequest();
327-
$getRequest->setKey($key);
328-
329-
$getOperation = new RequestOp();
330-
$getOperation->setRequestRange($getRequest);
331-
$request->setFailure([$getOperation]);
332-
}
308+
$request->setCompare($compare);
309+
$request->setSuccess($requestOperations);
310+
if($failureOperations !== null)
311+
$request->setFailure($failureOperations);
333312

334313
/** @var TxnResponse $response */
335314
list($response, $status) = $client->Txn($request, $this->getMetaData(), $this->getOptions())->wait();
336315
$this->validateStatus($status);
337316

338-
if ($returnNewValueOnFail && !$response->getSucceeded()) {
339-
/** @var ResponseOp $responseOp */
340-
$responseOp = $response->getResponses()[0];
317+
return $response;
318+
}
341319

342-
$getResponse = $responseOp->getResponseRange();
320+
/**
321+
* Creates RequestOp of Get operation for requestIf method
322+
*
323+
* @param string $key
324+
* @return RequestOp
325+
*/
326+
public function getGetOperation(string $key): RequestOp
327+
{
328+
$request = new RangeRequest();
329+
$request->setKey($key);
343330

344-
$field = $getResponse->getKvs();
331+
$operation = new RequestOp();
332+
$operation->setRequestRange($request);
345333

346-
if (count($field) === 0) {
347-
return false;
348-
}
334+
return $operation;
335+
}
349336

350-
return $field[0]->getValue();
351-
} else {
352-
return $response->getSucceeded();
353-
}
337+
/**
338+
* Creates RequestOp of Put operation for requestIf method
339+
*
340+
* @param string $key
341+
* @param string $value
342+
* @param int $leaseId
343+
* @return RequestOp
344+
*/
345+
public function getPutOperation(string $key, string $value, int $leaseId = 0): RequestOp
346+
{
347+
$request = new PutRequest();
348+
$request->setKey($key);
349+
$request->setValue($value);
350+
if($leaseId !== 0)
351+
$request->setLease($leaseId);
352+
353+
$operation = new RequestOp();
354+
$operation->setRequestPut($request);
355+
356+
return $operation;
357+
}
358+
359+
/**
360+
* Creates RequestOp of Delete operation for requestIf method
361+
*
362+
* @param string $key
363+
* @return RequestOp
364+
*/
365+
public function getDeleteOperation(string $key): RequestOp
366+
{
367+
$request = new DeleteRangeRequest();
368+
$request->setKey($key);
369+
370+
$operation = new RequestOp();
371+
$operation->setRequestDeleteRange($request);
372+
373+
return $operation;
374+
}
375+
376+
/**
377+
* Get an instance of Compare
378+
*
379+
* @param string $key
380+
* @param string $value
381+
* @param int $result see CompareResult class for available constants
382+
* @param int $target check constants in the CompareTarget class for available values
383+
* @return Compare
384+
*/
385+
public function getCompare(string $key, string $value, int $result, int $target): Compare
386+
{
387+
$compare = new Compare();
388+
$compare->setKey($key);
389+
$compare->setValue($value);
390+
$compare->setTarget($target);
391+
$compare->setResult($result);
392+
393+
return $compare;
354394
}
355395

356396
/**
@@ -401,6 +441,7 @@ protected function getAuthClient(): AuthClient
401441
return $this->authClient;
402442
}
403443

444+
404445
/**
405446
* Get an authentication token
406447
*
@@ -463,4 +504,58 @@ protected function validateStatus($status)
463504
throw ResponseStatusCodeExceptionFactory::getExceptionByCode($status->code, $status->details);
464505
}
465506
}
507+
508+
/**
509+
* @param string $key
510+
* @param string $compareValue
511+
* @return Compare
512+
*/
513+
protected function getCompareForIf(string $key, string $compareValue): Compare
514+
{
515+
if ($compareValue === false) {
516+
$compare = $this->getCompare($key, '0', CompareResult::EQUAL, CompareTarget::VERSION);
517+
} else {
518+
$compare = $this->getCompare($key, $compareValue, CompareResult::EQUAL, CompareTarget::VALUE);
519+
}
520+
return $compare;
521+
}
522+
523+
/**
524+
* @param bool $returnNewValueOnFail
525+
* @param TxnResponse $response
526+
* @return bool
527+
*/
528+
protected function getIfResponse(bool $returnNewValueOnFail, TxnResponse $response): bool
529+
{
530+
if ($returnNewValueOnFail && !$response->getSucceeded()) {
531+
/** @var ResponseOp $responseOp */
532+
$responseOp = $response->getResponses()[0];
533+
534+
$getResponse = $responseOp->getResponseRange();
535+
536+
$field = $getResponse->getKvs();
537+
538+
if (count($field) === 0) {
539+
return false;
540+
}
541+
542+
return $field[0]->getValue();
543+
} else {
544+
return $response->getSucceeded();
545+
}
546+
}
547+
548+
/**
549+
* @param string $key
550+
* @param bool $returnNewValueOnFail
551+
* @return array|null
552+
*/
553+
protected function getFailOperation(string $key, bool $returnNewValueOnFail)
554+
{
555+
$failOperation = null;
556+
if ($returnNewValueOnFail)
557+
$failOperation = [$this->getGetOperation($key)];
558+
559+
return $failOperation;
560+
}
466561
}

src/ClientInterface.php

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace Aternos\Etcd;
44

55
use Aternos\Etcd\Exception\Status\InvalidResponseStatusCodeException;
6+
use Etcdserverpb\Compare;
7+
use Etcdserverpb\RequestOp;
8+
use Etcdserverpb\TxnResponse;
69
use Exception;
710

811
/**
@@ -54,24 +57,74 @@ public function delete(string $key);
5457
* Put $value if $key value matches $previousValue otherwise $returnNewValueOnFail
5558
*
5659
* @param string $key
57-
* @param mixed $value The new value to set
58-
* @param mixed $previousValue The previous value to compare against
60+
* @param string $value The new value to set
61+
* @param bool|string $compareValue The previous value to compare against
5962
* @param bool $returnNewValueOnFail
6063
* @return bool|string
6164
* @throws InvalidResponseStatusCodeException
6265
*/
63-
public function putIf(string $key, $value, $previousValue, bool $returnNewValueOnFail = false);
66+
public function putIf(string $key, string $value, $compareValue, bool $returnNewValueOnFail = false);
6467

6568
/**
6669
* Delete if $key value matches $previous value otherwise $returnNewValueOnFail
6770
*
6871
* @param string $key
69-
* @param $previousValue
72+
* @param bool|string $compareValue The previous value to compare against
7073
* @param bool $returnNewValueOnFail
7174
* @return bool|string
7275
* @throws InvalidResponseStatusCodeException
76+
* @throws \Exception
7377
*/
74-
public function deleteIf(string $key, $previousValue, bool $returnNewValueOnFail = false);
78+
public function deleteIf(string $key, $compareValue, bool $returnNewValueOnFail = false);
79+
80+
/**
81+
* Execute $requestOperation if $key value matches $previous otherwise $returnNewValueOnFail
82+
*
83+
* @param string $key
84+
* @param array $requestOperations operations to perform on success, array of RequestOp objects
85+
* @param array|null $failureOperations operations to perform on failure, array of RequestOp objects
86+
* @param array $compare array of Compare objects
87+
* @return TxnResponse
88+
* @throws InvalidResponseStatusCodeException
89+
*/
90+
public function txnRequest(string $key, array $requestOperations, ?array $failureOperations, array $compare): TxnResponse;
91+
92+
/**
93+
* Get an instance of Compare
94+
*
95+
* @param string $key
96+
* @param string $value
97+
* @param int $result see CompareResult class for available constants
98+
* @param int $target check constants in the CompareTarget class for available values
99+
* @return Compare
100+
*/
101+
public function getCompare(string $key, string $value, int $result, int $target): Compare;
102+
103+
/**
104+
* Creates RequestOp of Get operation for requestIf method
105+
*
106+
* @param string $key
107+
* @return RequestOp
108+
*/
109+
public function getGetOperation(string $key): RequestOp;
110+
111+
/**
112+
* Creates RequestOp of Put operation for requestIf method
113+
*
114+
* @param string $key
115+
* @param string $value
116+
* @param int $leaseId
117+
* @return RequestOp
118+
*/
119+
public function getPutOperation(string $key, string $value, int $leaseId = 0): RequestOp;
120+
121+
/**
122+
* Creates RequestOp of Delete operation for requestIf method
123+
*
124+
* @param string $key
125+
* @return RequestOp
126+
*/
127+
public function getDeleteOperation(string $key): RequestOp;
75128

76129
/**
77130
* Get leaseID which can be used with etcd's put

0 commit comments

Comments
 (0)