Skip to content

Commit a11699a

Browse files
committed
Merge pull request #583: Expose Namespace in client requests metadata
(cherry picked from commit ac9e858)
1 parent 347e344 commit a11699a

File tree

5 files changed

+87
-72
lines changed

5 files changed

+87
-72
lines changed

src/Client/GRPC/BaseClient.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,14 @@ public function getConnection(): ConnectionInterface
237237
*/
238238
protected function invoke(string $method, object $arg, ?ContextInterface $ctx = null): mixed
239239
{
240-
$ctx ??= $this->context;
240+
$ctx ??= $this->getContext();
241241

242242
// Add the API key to the context
243243
$key = (string) $this->apiKey;
244244
if ($key !== '') {
245245
$ctx = $ctx->withMetadata([
246246
'Authorization' => ["Bearer $key"],
247-
]);
247+
] + $ctx->getMetadata());
248248
}
249249

250250
return $this->invokePipeline !== null

src/Client/ScheduleClient.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,20 @@ public function __construct(
5151
?ClientOptions $options = null,
5252
?DataConverterInterface $converter = null,
5353
) {
54-
$this->client = $serviceClient;
5554
$this->clientOptions = $options ?? new ClientOptions();
5655
$this->converter = $converter ?? DataConverter::createDefault();
5756
$this->marshaller = new Marshaller(
5857
new AttributeMapperFactory(new AttributeReader()),
5958
);
6059
$this->protoConverter = new ProtoToArrayConverter($this->converter);
60+
61+
// Set Temporal-Namespace metadata
62+
$context = $serviceClient->getContext();
63+
$this->client = $serviceClient->withContext(
64+
$context->withMetadata(
65+
['Temporal-Namespace' => [$this->clientOptions->namespace]] + $context->getMetadata(),
66+
),
67+
);
6168
}
6269

6370
public static function create(

src/Client/WorkflowClient.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,19 @@ public function __construct(
7474
?DataConverterInterface $converter = null,
7575
?PipelineProvider $interceptorProvider = null,
7676
) {
77-
$this->client = $serviceClient;
7877
$this->interceptorPipeline = ($interceptorProvider ?? new SimplePipelineProvider())
7978
->getPipeline(WorkflowClientCallsInterceptor::class);
8079
$this->clientOptions = $options ?? new ClientOptions();
8180
$this->converter = $converter ?? DataConverter::createDefault();
8281
$this->reader = new WorkflowReader($this->createReader());
82+
83+
// Set Temporal-Namespace metadata
84+
$context = $serviceClient->getContext();
85+
$this->client = $serviceClient->withContext(
86+
$context->withMetadata(
87+
['Temporal-Namespace' => [$this->clientOptions->namespace]] + $context->getMetadata(),
88+
),
89+
);
8390
}
8491

8592
/**

tests/Unit/Client/GRPC/BaseClientTestCase.php

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Temporal\Tests\Unit\Client\GRPC;
66

7-
use DateTimeImmutable;
87
use PHPUnit\Framework\TestCase;
98
use Temporal\Api\Workflowservice\V1\GetSystemInfoRequest;
109
use Temporal\Api\Workflowservice\V1\GetSystemInfoResponse;
@@ -48,18 +47,14 @@ public function testGetCapabilitiesClearsCache(): void
4847
public function testClose(): void
4948
{
5049
$client = $this->createClientMock(static fn() => new class extends WorkflowServiceClient {
51-
public function __construct()
52-
{
53-
}
50+
public function __construct() {}
5451

5552
public function getConnectivityState($try_to_connect = false): int
5653
{
5754
return ConnectionState::TransientFailure->value;
5855
}
5956

60-
public function close(): void
61-
{
62-
}
57+
public function close(): void {}
6358
});
6459
$client->close();
6560

@@ -105,7 +100,7 @@ public function testContextGetDeadlineWithoutDeadline(): void
105100
public function testContextGetDeadlineWithStaticDeadline(): void
106101
{
107102
$client = $this->createClientMock();
108-
$context = $client->getContext()->withDeadline(new DateTimeImmutable('+1 second'));
103+
$context = $client->getContext()->withDeadline(new \DateTimeImmutable('+1 second'));
109104

110105
$this->assertSame($context->getDeadline(), $context->getDeadline());
111106
}
@@ -127,11 +122,13 @@ public function testWithAuthKey(): void
127122
$ctx1 = $client->testCall()->ctx;
128123
self::assertInstanceOf(ContextInterface::class, $ctx1);
129124
$this->assertArrayNotHasKey('Authorization', $ctx1->getMetadata());
125+
$keysBefore = \count($ctx1->getMetadata());
130126

131127
$ctx2 = $client2->testCall()->ctx;
132128
self::assertInstanceOf(ContextInterface::class, $ctx2);
133129
$this->assertArrayHasKey('Authorization', $ctx2->getMetadata());
134130
$this->assertSame(['Bearer test-key'], $ctx2->getMetadata()['Authorization']);
131+
$this->assertSame($keysBefore + 1, \count($ctx2->getMetadata()), 'API Key doesnt affect other metadata');
135132
}
136133

137134
public function testWithDynamicAuthKey(): void
@@ -158,22 +155,21 @@ public function __toString(): string
158155

159156
public function testServiceClientCallDeadlineReached(): void
160157
{
161-
$client = $this->createClientMock(fn() => new class() extends WorkflowServiceClient {
158+
$client = $this->createClientMock(static fn() => new class extends WorkflowServiceClient {
162159
public function __construct() {}
163-
public function testCall()
164-
{
165-
throw new class((object)['code' => StatusCode::UNKNOWN, 'metadata' => []])
166-
extends ServiceClientException {
167-
};
168-
}
169-
public function close(): void
160+
161+
public function testCall(): void
170162
{
163+
throw new class((object) ['code' => StatusCode::UNKNOWN, 'metadata' => []]) extends ServiceClientException {};
171164
}
165+
166+
public function close(): void {}
172167
})->withInterceptorPipeline(null);
173168

174-
$client = $client->withContext($client->getContext()
175-
->withDeadline(new DateTimeImmutable('-1 second'))
176-
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(2)) // stop if deadline doesn't work
169+
$client = $client->withContext(
170+
$client->getContext()
171+
->withDeadline(new \DateTimeImmutable('-1 second'))
172+
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(2)), // stop if deadline doesn't work
177173
);
178174

179175
self::expectException(TimeoutException::class);
@@ -183,20 +179,21 @@ public function close(): void
183179

184180
public function testServiceClientCallCustomException(): void
185181
{
186-
$client = $this->createClientMock(fn() => new class() extends WorkflowServiceClient {
182+
$client = $this->createClientMock(static fn() => new class extends WorkflowServiceClient {
187183
public function __construct() {}
188-
public function testCall()
184+
185+
public function testCall(): void
189186
{
190187
throw new \RuntimeException('foo');
191188
}
192-
public function close(): void
193-
{
194-
}
189+
190+
public function close(): void {}
195191
})->withInterceptorPipeline(null);
196192

197-
$client = $client->withContext($client->getContext()
198-
->withDeadline(new DateTimeImmutable('-1 second'))
199-
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(2)) // stop if deadline doesn't work
193+
$client = $client->withContext(
194+
$client->getContext()
195+
->withDeadline(new \DateTimeImmutable('-1 second'))
196+
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(2)), // stop if deadline doesn't work
200197
);
201198

202199
self::expectException(\RuntimeException::class);
@@ -210,31 +207,32 @@ public function close(): void
210207
*/
211208
public function testServiceClientCallMaximumAttemptsReached(): void
212209
{
213-
$client = $this->createClientMock(fn() => new class() extends WorkflowServiceClient {
210+
$client = $this->createClientMock(fn() => new class extends WorkflowServiceClient {
214211
public function __construct() {}
215-
public function testCall()
212+
213+
public function testCall(): void
216214
{
217215
static $counter = 0;
218-
throw new class(++$counter)
219-
extends ServiceClientException {
216+
throw new class(++$counter) extends ServiceClientException {
220217
public function __construct(public int $attempt)
221218
{
222-
parent::__construct((object)['code' => StatusCode::UNKNOWN, 'metadata' => []]);
219+
parent::__construct((object) ['code' => StatusCode::UNKNOWN, 'metadata' => []]);
223220
}
221+
224222
public function isTestError(): bool
225223
{
226224
return true;
227225
}
228226
};
229227
}
230-
public function close(): void
231-
{
232-
}
228+
229+
public function close(): void {}
233230
})->withInterceptorPipeline(null);
234231

235-
$client = $client->withContext($client->getContext()
236-
->withDeadline(new DateTimeImmutable('+2 seconds')) // stop if attempts don't work
237-
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(3)->withBackoffCoefficient(1))
232+
$client = $client->withContext(
233+
$client->getContext()
234+
->withDeadline(new \DateTimeImmutable('+2 seconds')) // stop if attempts don't work
235+
->withRetryOptions(RpcRetryOptions::new()->withMaximumAttempts(3)->withBackoffCoefficient(1)),
238236
);
239237

240238
try {
@@ -249,41 +247,38 @@ public function close(): void
249247
private function createClientMock(?callable $serviceClientFactory = null): BaseClient
250248
{
251249
return (new class($serviceClientFactory ?? static fn() => new class extends WorkflowServiceClient {
252-
public function __construct()
253-
{
254-
}
250+
public function __construct() {}
255251

256252
public function getConnectivityState($try_to_connect = false): int
257253
{
258254
return ConnectionState::Ready->value;
259255
}
260256

261-
public function close(): void
262-
{
263-
}
257+
public function close(): void {}
264258
}) extends ServiceClient {
259+
265260
public function getSystemInfo(
266261
GetSystemInfoRequest $arg,
267-
ContextInterface $ctx = null,
262+
?ContextInterface $ctx = null,
268263
): GetSystemInfoResponse {
269264
return (new GetSystemInfoResponse())
270-
->setCapabilities((new Capabilities)->setSupportsSchedules(true))
265+
->setCapabilities((new Capabilities())->setSupportsSchedules(true))
271266
->setServerVersion('1.2.3');
272267
}
273268

274269
public function testCall(): mixed
275270
{
276-
return $this->invoke("testCall", (object)[], null);
271+
return $this->invoke("testCall", (object) [], null);
277272
}
278273
})->withInterceptorPipeline(
279274
Pipeline::prepare([new class implements \Temporal\Interceptor\GrpcClientInterceptor {
280275
public function interceptCall(
281276
string $method,
282277
object $arg,
283278
ContextInterface $ctx,
284-
callable $next
279+
callable $next,
285280
): object {
286-
return (object)['method' => $method, 'arg' => $arg, 'ctx' => $ctx, 'next' => $next];
281+
return (object) ['method' => $method, 'arg' => $arg, 'ctx' => $ctx, 'next' => $next];
287282
}
288283
}]),
289284
);

0 commit comments

Comments
 (0)