Skip to content

Commit e7e840c

Browse files
committed
Added new Async class files
1 parent 1d17117 commit e7e840c

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

src/AsyncClient.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace DigitalOceanV2;
4+
5+
use DigitalOceanV2\Client;
6+
use DigitalOceanV2\HttpClient\Builder;
7+
use DigitalOceanV2\HttpClient\AsyncBuilder;
8+
use DigitalOceanV2\HttpClient\Plugin\Authentication;
9+
10+
class AsyncClient extends Client
11+
{
12+
private AsyncBuilder $asyncBuilder;
13+
14+
public function __construct(?AsyncBuilder $asyncBuilder = null, ?string $apiKey = null, ?Builder $httpClientBuilder = null)
15+
{
16+
parent::__construct($httpClientBuilder);
17+
18+
$baseUri = self::BASE_URL;
19+
$headers = [
20+
'Accept' => 'application/json',
21+
'User-Agent' => self::USER_AGENT,
22+
];
23+
if ($apiKey) {
24+
$headers['Authorization'] = 'Bearer ' . $apiKey;
25+
}
26+
$plugins = [];
27+
if ($apiKey) {
28+
$plugins[] = new Authentication($apiKey);
29+
}
30+
$this->asyncBuilder = $asyncBuilder ?? new AsyncBuilder($baseUri, $headers, $plugins);
31+
}
32+
33+
/**
34+
* Authenticate with a token (adds Authentication plugin).
35+
*/
36+
public function authenticate(string $token): void
37+
{
38+
$this->asyncBuilder = new AsyncBuilder(
39+
self::BASE_URL,
40+
[
41+
'Accept' => 'application/json',
42+
'User-Agent' => self::USER_AGENT,
43+
'Authorization' => 'Bearer ' . $token
44+
],
45+
[new Authentication($token)]
46+
);
47+
}
48+
49+
/**
50+
* Build and execute async requests for multiple endpoints.
51+
* @param array $requests Array of ['key' => 'uri']
52+
* @return array Array of responses keyed by 'key'
53+
*/
54+
public function fetchAsync(array $requests)
55+
{
56+
$promises = $this->asyncBuilder->buildAsyncRequests($requests);
57+
return $this->asyncBuilder->waitAll($promises);
58+
}
59+
60+
/**
61+
* Get the underlying AsyncBuilder instance.
62+
*/
63+
public function getAsyncBuilder(): AsyncBuilder
64+
{
65+
return $this->asyncBuilder;
66+
}
67+
}

src/HttpClient/AsyncBuilder.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
namespace DigitalOceanV2\HttpClient;
3+
4+
use Http\Client\Common\Plugin;
5+
use Http\Client\Common\PluginClientFactory;
6+
use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
7+
use Http\Client\Common\Plugin\AddHostPlugin;
8+
use Http\Client\Common\PluginClient;
9+
use Http\Discovery\HttpAsyncClientDiscovery;
10+
use Http\Discovery\Psr17FactoryDiscovery;
11+
use Http\Message\RequestFactory;
12+
use Http\Promise\Promise;
13+
use Psr\Http\Message\RequestFactoryInterface;
14+
use Psr\Http\Message\UriFactoryInterface;
15+
16+
final class AsyncBuilder extends Builder
17+
{
18+
private $httpAsyncClient;
19+
private $requestFactory;
20+
private $uriFactory;
21+
private $plugins;
22+
private $pluginClient;
23+
private $baseUri;
24+
25+
public function __construct(
26+
?string $baseUri = null,
27+
array $defaultHeaders = [],
28+
array $plugins = []
29+
) {
30+
$this->httpAsyncClient = HttpAsyncClientDiscovery::find();
31+
$this->requestFactory = Psr17FactoryDiscovery::findRequestFactory();
32+
$this->uriFactory = Psr17FactoryDiscovery::findUriFactory();
33+
$this->baseUri = $baseUri ?? 'https://api.digitalocean.com';
34+
35+
// Add default header plugin
36+
$this->plugins = $plugins;
37+
if (!empty($defaultHeaders)) {
38+
$this->plugins[] = new HeaderDefaultsPlugin($defaultHeaders);
39+
}
40+
// Add host plugin
41+
$this->plugins[] = new AddHostPlugin($this->uriFactory->createUri($this->baseUri));
42+
43+
// Compose plugin client for async
44+
$this->pluginClient = new PluginClient($this->httpAsyncClient, $this->plugins);
45+
}
46+
47+
public function getAsyncClient()
48+
{
49+
return $this->pluginClient;
50+
}
51+
52+
public function getRequestFactory(): RequestFactoryInterface
53+
{
54+
return $this->requestFactory;
55+
}
56+
57+
public function getUriFactory(): UriFactoryInterface
58+
{
59+
return $this->uriFactory;
60+
}
61+
62+
/**
63+
* Build async GET requests for multiple endpoints.
64+
* @param array $requests Array of ['key' => 'uri']
65+
* @return array Array of promises keyed by 'key'
66+
*/
67+
public function buildAsyncRequests(array $requests)
68+
{
69+
$promises = [];
70+
foreach ($requests as $key => $uri) {
71+
$request = $this->requestFactory->createRequest('GET', $uri);
72+
$promises[$key] = $this->pluginClient->sendAsyncRequest($request);
73+
}
74+
return $promises;
75+
}
76+
77+
/**
78+
* Wait for all promises to complete and return results.
79+
* @param array $promises
80+
* @return array
81+
*/
82+
public function waitAll(array $promises)
83+
{
84+
// There is no PromiseSettler in php-http/promise, so we manually wait for each
85+
$results = [];
86+
foreach ($promises as $key => $promise) {
87+
$results[$key] = $promise->wait();
88+
}
89+
return $results;
90+
}
91+
}

0 commit comments

Comments
 (0)