Skip to content

Commit a978d8b

Browse files
committed
feat: implement fiber based api for polling operation
1 parent 37832d2 commit a978d8b

4 files changed

Lines changed: 116 additions & 0 deletions

File tree

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,56 @@ composer require cbws/php-cbws
2323

2424
## Usage
2525

26+
### Long-running operations
27+
28+
Many interactions with the CBWS cloud platform will be long-running operations that run on the background, these can
29+
be polled until the operation has finished. After which the response or error will be available.
30+
31+
### Getting the current operation status
32+
33+
Operations have a `get()` method that fetches the current state of the operation.
34+
35+
```php
36+
<?php
37+
$operation = $machine->stop();
38+
39+
// Get the latest status of the operation
40+
$operation = $operation->get();
41+
42+
var_dump($operation->getDone());
43+
var_dump($operation->getResponse());
44+
if ($operation->getError() !== null) {
45+
throw $operation->getError();
46+
}
47+
```
48+
49+
### Async/await with PHP fibers
50+
51+
With the built-in PHP fibers it is possible to wait until the operation has finished, either successfully or with an error:
52+
53+
```php
54+
$operation = $machine->stop();
55+
56+
// Get the fiber that will wait until the operation has finished.
57+
$fiber = $operation->fiber();
58+
$fiber->start();
59+
60+
while (!$fiber->isTerminated()) {
61+
// Get intermediate operation state
62+
$operation = $fiber->resume();
63+
}
64+
65+
// Finished operation
66+
$operation = $fiber->getReturn();
67+
68+
var_dump($operation->getDone());
69+
var_dump($operation->getResponse());
70+
if ($operation->getError() !== null) {
71+
throw $operation->getError();
72+
}
73+
74+
```
75+
2676
### Compute
2777

2878
```php

src/Common/Longrunning/Model/Operation.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Cbws\Sdk\Common\Longrunning\Operations;
1111
use Cbws\Sdk\Common\Longrunning\ResponseInterface;
1212
use Exception;
13+
use Fiber;
1314

1415
/**
1516
* @template TMetadata of MetadataInterface
@@ -86,6 +87,16 @@ public function await(): self
8687
return $this->client->awaitOperation($this->getName(), $this->metadataType, $this->responseType);
8788
}
8889

90+
/**
91+
* Provider Fiber for waiting until the operation has finished, either successfully or with an error.
92+
*
93+
* @return Fiber<?int, ?int, Operation<TMetadata, TResponse>, Operation<TMetadata, TResponse>>
94+
*/
95+
public function fiber(): Fiber
96+
{
97+
return $this->client->fiberOperation($this->getName(), $this->metadataType, $this->responseType);
98+
}
99+
89100
public function __debugInfo()
90101
{
91102
return [

src/Common/Longrunning/Operations.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Cbws\Sdk\Common\Longrunning\V1alpha1\DeleteOperationRequest;
1313
use Cbws\Sdk\Common\Longrunning\V1alpha1\GetOperationRequest;
1414
use Cbws\Sdk\Common\Longrunning\V1alpha1\WaitOperationRequest;
15+
use Fiber;
1516
use Generator;
1617
use Google\Protobuf\GPBEmpty;
1718

@@ -181,4 +182,38 @@ public function awaitOperation(string $name, string $metadataType, string $respo
181182
/** @phpstan-var Operation<TMetadata, TResponse> */
182183
return $operation;
183184
}
185+
186+
/**
187+
* Provider Fiber for waiting until the operation has finished, either successfully or with an error.
188+
*
189+
* @template TMetadata of MetadataInterface
190+
* @template TResponse of ResponseInterface
191+
*
192+
* @param class-string<TMetadata> $metadataType
193+
* @param class-string<TResponse> $responseType
194+
*
195+
* @return Fiber<?int, ?int, Operation<TMetadata, TResponse>, Operation<TMetadata, TResponse>>
196+
*/
197+
public function fiberOperation(string $name, string $metadataType, string $responseType): Fiber
198+
{
199+
/** @phpstan-var Fiber<?int, ?int, Operation<TMetadata, TResponse>, Operation<TMetadata, TResponse>> */
200+
return new Fiber(function (?int $timeout = 5) use ($name, $metadataType, $responseType) {
201+
do {
202+
$operation = $this->waitOperation($name, $metadataType, $responseType, $timeout ?: 5);
203+
204+
// We should see if we can have a way of providing a non-blocking way to implement fibers, doing get over
205+
// and over again would put a massive load on our service.
206+
// if ($timeout !== null) {
207+
// $operation = $this->waitOperation($name, $metadataType, $responseType, $timeout);
208+
// } else {
209+
// $operation = $this->getOperation($name, $metadataType, $responseType);
210+
// }
211+
212+
/** @phpstan-var ?int $timeout */
213+
$timeout = Fiber::suspend($operation);
214+
} while (!$operation->getDone());
215+
216+
return $operation;
217+
});
218+
}
184219
}

tests/Integration/Compute/MachinesTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,26 @@ public function test_start_machine(): void
9292
self::assertTrue($operation->getDone());
9393
}
9494

95+
public function test_start_machine_fiber(): void
96+
{
97+
assert($this->client !== null);
98+
$machine = $this->client->machines()->get('php-cbws-test1');
99+
$fiber = $machine->start()->fiber();
100+
$fiber->start();
101+
102+
// Wait until operation has finished
103+
while (!$fiber->isTerminated()) {
104+
$fiber->resume();
105+
}
106+
107+
$operation = $fiber->getReturn();
108+
109+
if ($operation->getError() !== null) {
110+
throw $operation->getError();
111+
}
112+
self::assertTrue($operation->getDone());
113+
}
114+
95115
// public function test_update_instance(): void
96116
// {
97117
// $operation = $this->client->updateInstance('php-cbws-test1', Instance::create()->withCPU(2));

0 commit comments

Comments
 (0)