Skip to content

Commit 144a1cf

Browse files
authored
Merge pull request #20 from ByteInternet/fix_setting_job
service/settings: Fix job polling mechanism
2 parents 2c7a821 + 9235483 commit 144a1cf

File tree

6 files changed

+156
-31
lines changed

6 files changed

+156
-31
lines changed

src/Defaults.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hypernode\Api;
6+
7+
class Defaults {
8+
const HYPERNODE_API_URL = 'https://api.hypernode.com/';
9+
}

src/HypernodeClientFactory.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
class HypernodeClientFactory
1818
{
19-
public const HYPERNODE_API_URL = 'https://api.hypernode.com/';
20-
2119
public static function create(string $authToken, ?ClientInterface $httpClient = null): HypernodeClient
2220
{
2321
$httpHeaders = [
@@ -29,7 +27,7 @@ public static function create(string $authToken, ?ClientInterface $httpClient =
2927
'Accept' => 'application/json',
3028
'Content-Type' => 'application/json',
3129
];
32-
$httpClient = self::getHttpClient(self::HYPERNODE_API_URL, $httpHeaders, $httpClient);
30+
$httpClient = self::getHttpClient(Defaults::HYPERNODE_API_URL, $httpHeaders, $httpClient);
3331

3432
$apiClient = new HttpMethodsClient(
3533
$httpClient, Psr17FactoryDiscovery::findRequestFactory(), Psr17FactoryDiscovery::findStreamFactory()

src/Resource/Logbook/Job.php

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Hypernode\Api\HypernodeClient;
88
use Hypernode\Api\Resource\AbstractResource;
9+
use Hypernode\Api\Service\App;
910

1011
/**
1112
* @property-read string $result
@@ -15,17 +16,19 @@
1516
*/
1617
class Job extends AbstractResource
1718
{
18-
private string $url;
19+
private string $id;
20+
private string $appName;
1921
private bool $exists = false;
2022
private bool $running = false;
23+
private bool $success = false;
2124
private bool $complete = false;
22-
2325
protected HypernodeClient $client;
2426

25-
public function __construct(HypernodeClient $client, string $urlOrId, array $data = [])
27+
public function __construct(HypernodeClient $client, string $appName, string $id, array $data = [])
2628
{
2729
$this->client = $client;
28-
$this->url = $urlOrId;
30+
$this->appName = $appName;
31+
$this->id = $id;
2932
$this->data = $data;
3033
}
3134

@@ -37,37 +40,60 @@ public function __construct(HypernodeClient $client, string $urlOrId, array $dat
3740
*/
3841
public function refresh()
3942
{
40-
$response = $this->client->api->get($this->url);
43+
$url = sprintf(App::V1_APP_FLOWS_URL, $this->appName) . '?' . http_build_query(['tracker_uuid' => $this->id]);
44+
$response = $this->client->api->get($url);
45+
$this->data = $this->client->getJsonFromResponse($response);
4146

42-
if ($response->getStatusCode() === 404) {
47+
if ($response->getStatusCode() === 404 || $this->data['count'] === 0) {
4348
$this->data = [];
4449
$this->exists = false;
4550
$this->running = false;
4651
return;
4752
}
4853

49-
if ($response->getStatusCode() === 303) {
50-
$this->data = [];
51-
$this->exists = true;
52-
$this->running = false;
53-
$this->complete = true;
54-
return;
54+
$this->exists = true;
55+
56+
$result = $this->data['results'][0];
57+
switch ($result['state']) {
58+
case 'running':
59+
$this->running = true;
60+
break;
61+
case 'success':
62+
$this->success = true;
63+
$this->running = false;
64+
$this->complete = true;
65+
break;
66+
case 'reverted':
67+
$this->running = false;
68+
$this->complete = true;
69+
break;
5570
}
5671

5772
$this->client->maybeThrowApiExceptions($response);
73+
}
5874

59-
$this->data = $this->client->getJsonFromResponse($response);
60-
$this->exists = true;
61-
$this->running = true;
75+
public function id()
76+
{
77+
return $this->id;
6278
}
6379

6480
public function exists(): bool
6581
{
6682
return $this->exists;
6783
}
6884

85+
public function running(): bool
86+
{
87+
return $this->running;
88+
}
89+
6990
public function completed(): bool
7091
{
7192
return $this->complete;
7293
}
73-
}
94+
95+
public function success(): bool
96+
{
97+
return $this->success;
98+
}
99+
}

src/Service/Settings.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
namespace Hypernode\Api\Service;
66

7+
use Hypernode\Api\Defaults;
78
use Hypernode\Api\Resource\Logbook\Job;
89

910
class Settings extends AbstractService
1011
{
12+
public const JOB_URL_REGEX = '#' . Defaults::HYPERNODE_API_URL. 'logbook/v1/jobs/(.*)/#';
13+
1114
public function set(string $app, string $key, string $value): ?Job
1215
{
1316
return $this->setBatch($app, [$key => $value]);
@@ -21,7 +24,11 @@ public function setBatch(string $app, array $settings): ?Job
2124
$this->client->maybeThrowApiExceptions($response);
2225

2326
if ($response->getStatusCode() === 202) {
24-
$job = new Job($this->client, $response->getHeaderLine('Location'));
27+
$location = $response->getHeaderLine('Location');
28+
if (!preg_match(self::JOB_URL_REGEX, $location, $matches)) {
29+
return null;
30+
}
31+
$job = new Job($this->client, $app, $matches[1]);
2532
return $job;
2633
}
2734

tests/unit/Resource/Logbook/JobTest.php

Lines changed: 92 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ class JobTest extends HypernodeClientTestCase
1616
protected function setUp(): void
1717
{
1818
parent::setUp();
19-
$this->jobUrl = "https://api.hypernode.com/logbook/v1/jobs/abcd/";
20-
$this->job = new Job($this->client, $this->jobUrl);
19+
$this->job = new Job($this->client, 'johndoe', 'abcd');
2120
}
2221

2322
public function testIsInstanceOfAbstractResource()
@@ -29,17 +28,100 @@ public function testRefresh()
2928
{
3029
$this->responses->append(
3130
new Response(404, [], json_encode([])),
31+
new Response(200, [], json_encode(['count' => 0, 'results' => []])),
3232
new Response(200, [], json_encode([
33-
'result' => 'pending',
34-
'flow_name' => 'update_node',
35-
'app_name' => 'johndoe'
33+
'count' => 1,
34+
'results' => [
35+
[
36+
'uuid' => 'abcd',
37+
'state' => NULL,
38+
'name' => 'update_node'
39+
]
40+
]
3641
])),
3742
new Response(200, [], json_encode([
38-
'result' => 'running',
39-
'flow_name' => 'update_node',
40-
'app_name' => 'johndoe'
43+
'count' => 1,
44+
'results' => [
45+
[
46+
'uuid' => 'abcd',
47+
'state' => 'running',
48+
'name' => 'update_node'
49+
]
50+
]
51+
])),
52+
new Response(200, [], json_encode([
53+
'count' => 1,
54+
'results' => [
55+
[
56+
'uuid' => 'abcd',
57+
'state' => 'success',
58+
'name' => 'update_node'
59+
]
60+
]
61+
])),
62+
);
63+
64+
$this->job->refresh();
65+
66+
$this->assertFalse($this->job->exists());
67+
$this->assertFalse($this->job->completed());
68+
69+
$this->job->refresh();
70+
71+
$this->assertFalse($this->job->exists());
72+
$this->assertFalse($this->job->completed());
73+
74+
$this->job->refresh();
75+
76+
$this->assertTrue($this->job->exists());
77+
$this->assertFalse($this->job->completed());
78+
79+
$this->job->refresh();
80+
81+
$this->assertTrue($this->job->exists());
82+
$this->assertFalse($this->job->completed());
83+
84+
$this->job->refresh();
85+
86+
$this->assertTrue($this->job->exists());
87+
$this->assertTrue($this->job->completed());
88+
$this->assertTrue($this->job->success());
89+
}
90+
91+
public function testRefreshFailedJob()
92+
{
93+
$this->responses->append(
94+
new Response(404, [], json_encode([])),
95+
new Response(200, [], json_encode([
96+
'count' => 1,
97+
'results' => [
98+
[
99+
'uuid' => 'abcd',
100+
'state' => NULL,
101+
'name' => 'update_node'
102+
]
103+
]
104+
])),
105+
new Response(200, [], json_encode([
106+
'count' => 1,
107+
'results' => [
108+
[
109+
'uuid' => 'abcd',
110+
'state' => 'running',
111+
'name' => 'update_node'
112+
]
113+
]
114+
])),
115+
new Response(200, [], json_encode([
116+
'count' => 1,
117+
'results' => [
118+
[
119+
'uuid' => 'abcd',
120+
'state' => 'reverted',
121+
'name' => 'update_node'
122+
]
123+
]
41124
])),
42-
new Response(303, [], json_encode([])),
43125
);
44126

45127
$this->job->refresh();
@@ -61,6 +143,7 @@ public function testRefresh()
61143

62144
$this->assertTrue($this->job->exists());
63145
$this->assertTrue($this->job->completed());
146+
$this->assertFalse($this->job->success());
64147
}
65148

66149
public function testExistsReturnsFalseByDefault()

tests/unit/Service/SettingsTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ public function testSetSingleSettingToDifferentValue()
3333
{
3434
$jobUrl = 'https://api.hypernode.com/logbook/v1/jobs/abcd/';
3535
$this->responses->append(
36-
new Response(202, ['Location: ' . $jobUrl], null),
36+
new Response(202, ['Location' => $jobUrl], null),
3737
);
3838

3939
$job = $this->client->settings->set('johndoe', 'php_version', '8.1');
4040

4141
$request = $this->responses->getLastRequest();
4242

4343
$this->assertNotNull($job);
44+
$this->assertEquals('abcd', $job->id());
4445
$this->assertEquals('PATCH', $request->getMethod());
4546
$this->assertEquals('/v2/app/johndoe/', $request->getUri());
4647
$this->assertJson((string)$request->getBody());
@@ -54,7 +55,7 @@ public function testSetMultipleSettings()
5455
{
5556
$jobUrl = 'https://api.hypernode.com/logbook/v1/jobs/abcd/';
5657
$this->responses->append(
57-
new Response(202, ['Location: ' . $jobUrl], null),
58+
new Response(202, ['Location' => $jobUrl], null),
5859
);
5960

6061
$job = $this->client->settings->setBatch(
@@ -68,6 +69,7 @@ public function testSetMultipleSettings()
6869
$request = $this->responses->getLastRequest();
6970

7071
$this->assertNotNull($job);
72+
$this->assertEquals('abcd', $job->id());
7173
$this->assertEquals('PATCH', $request->getMethod());
7274
$this->assertEquals('/v2/app/johndoe/', $request->getUri());
7375
$this->assertJson((string)$request->getBody());

0 commit comments

Comments
 (0)