Skip to content

Commit

Permalink
Add ClientConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
roxblnfk committed Aug 29, 2024
1 parent d94eb74 commit 38b4118
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 321 deletions.
5 changes: 3 additions & 2 deletions src/Bootloader/TemporalBridgeBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ protected function initConfig(EnvironmentInterface $env): void
[
'connection' => $env->get('TEMPORAL_CONNECTION', 'default'),
'connections' => [
'default' => ConnectionConfig::create(
'default' => ConnectionConfig::new(
address: $env->get('TEMPORAL_ADDRESS', '127.0.0.1:7233'),
),
],
Expand All @@ -173,7 +173,8 @@ protected function initConfig(EnvironmentInterface $env): void

protected function initServiceClient(TemporalConfig $config): ServiceClientInterface
{
$connection = $config->getConnection($config->getDefaultConnection());
$client = $config->getClientConfig($config->getDefaultClient());
$connection = $client->connection;

return $connection->isSecure()
? ServiceClient::createSSL(
Expand Down
60 changes: 60 additions & 0 deletions src/Config/ClientConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace Spiral\TemporalBridge\Config;

use Temporal\Client\ClientOptions;
use Temporal\Client\GRPC\Context;
use Temporal\Client\GRPC\ContextInterface;

/**
* Temporal Client configuration.
*
* ClientConfig::new(
* ConnectionConfig::new('localhost:7233')
* ->withTls(
* privateKey: '/my-project.key',
* certChain: '/my-project.pem',
* ),
* (new ClientOptions())
* ->withNamespace('default'),
* Context::default()
* ->withTimeout(4.5)
* ->withRetryOptions(
* RpcRetryOptions::new()
* ->withMaximumAttempts(5)
* ->withInitialInterval(3)
* ->withMaximumInterval(10)
* ->withBackoffCoefficient(1.6)
* ),
* ),
* ),
*/
final class ClientConfig
{
private function __construct(
public readonly ConnectionConfig $connection,
public readonly ClientOptions $options,
public readonly ContextInterface $context,
) {}

/**
* Create a new client configuration.
*
* @param ConnectionConfig $connection
* @param ClientOptions|null $options
* @param ContextInterface|null $context Default Service Client context.
*/
public static function new(
ConnectionConfig $connection,
?ClientOptions $options = null,
?ContextInterface $context = null,
): self {
return new self(
$connection,
$options ?? new ClientOptions(),
$context ?? Context::default(),
);
}
}
33 changes: 8 additions & 25 deletions src/Config/ConnectionConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
namespace Spiral\TemporalBridge\Config;

/**
* Temporal connection configuration.
* Temporal connection and credentials configuration.
*
* How to connect to local Temporal server:
*
* ConnectionConfig::create('localhost:7233'),
* ConnectionConfig::new('localhost:7233'),
*
* How to connect to Temporal Cloud:
*
* ConnectionConfig::createCloud(
* address: 'foo-bar-default.baz.tmprl.cloud:7233',
* privateKey: '/my-project.key',
* certChain: '/my-project.pem',
* ),
* ConnectionConfig::new('foo-bar-default.baz.tmprl.cloud:7233')
* ->withTls(
* privateKey: '/my-project.key',
* certChain: '/my-project.pem',
* ),
*/
final class ConnectionConfig
{
Expand Down Expand Up @@ -45,29 +45,12 @@ public function isSecure(): bool
/**
* @param non-empty-string $address
*/
public static function create(
public static function new(
string $address,
): self {
return new self($address);
}

/**
* Used to connect to Temporal Cloud.
*
* @link https://docs.temporal.io/cloud/get-started
*
* @param non-empty-string $address
* @param non-empty-string $privateKey Client private key string or file in PEM format.
* @param non-empty-string $certChain Client certificate chain string or file in PEM format.
*/
public static function createCloud(
string $address,
string $privateKey,
string $certChain,
): self {
return new self($address, new TlsConfig(privateKey: $privateKey, certChain: $certChain));
}

/**
* Set the TLS configuration for the connection.
*
Expand Down
91 changes: 60 additions & 31 deletions src/Config/TemporalConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,11 @@
* }
*
* @property array{
* address?: non-empty-string|null,
* connection: non-empty-string,
* connections: array<non-empty-string, ConnectionConfig>,
* temporalNamespace: non-empty-string,
* client: non-empty-string,
* clients: array<non-empty-string, ClientConfig>,
* defaultWorker: non-empty-string,
* workers: array<non-empty-string, WorkerOptions|TWorker>,
* interceptors?: TInterceptor[],
* clientOptions?: ClientOptions
* } $config
*/
final class TemporalConfig extends InjectableConfig
Expand All @@ -37,54 +34,76 @@ final class TemporalConfig extends InjectableConfig
public const CONFIG = 'temporal';

protected array $config = [
'connection' => 'default',
'connections' => [],
'temporalNamespace' => 'default',
'client' => 'default',
'clients' => [],
'defaultWorker' => WorkerFactoryInterface::DEFAULT_TASK_QUEUE,
'workers' => [],
'interceptors' => [],
'clientOptions' => null,
];

public function __construct(array $config = [])
{
// Legacy support. Will be removed in further versions.
// If you read this, please remove `address` option from your configuration and use `clients` instead.
$address = $config['address'] ?? null;
if ($address !== null) {
\trigger_error(
'Temporal options `address`, `clientOptions`, `temporalNamespace` are deprecated.',
\E_USER_DEPRECATED,
);

// Create a default client configuration from the legacy options.
$namespace = $config['temporalNamespace'] ?? 'default';
$clientOptions = ($config['clientOptions'] ?? new ClientOptions())
->withNamespace($namespace);

$config['client'] = 'default';
$config['clients']['default'] = ClientConfig::new(
ConnectionConfig::new(address: $address),
$clientOptions,
);
}

parent::__construct($config);
}

/**
* Get default namespace for Temporal client.
*
* @return non-empty-string
*
* @deprecated
*/
public function getTemporalNamespace(): string
{
return $this->config['temporalNamespace'];
$client = $this->getDefaultClient();
return match(true) {
isset($this->config['clients'][$client]) => $this->config['clients'][$client]->options->namespace,
isset($this->config['temporalNamespace']) => $this->config['temporalNamespace'],
default => 'default',
};
}

public function getDefaultConnection(): string
public function getDefaultClient(): string
{
return $this->config['connection'] ?? 'default';
return $this->config['client'] ?? 'default';
}

public function getConnection(string $name): ConnectionConfig
public function getClientConfig(string $name): ClientConfig
{
// Legacy support. Will be removed in further versions.
// If you read this, please remove address from your configuration and use connections instead.
$address = $this->config['address'] ?? null;
if ($address !== null) {
\trigger_error(
'Using `address` is deprecated, use `connections` instead.',
\E_USER_DEPRECATED,
);
return ConnectionConfig::create(address: $address);
}

if (isset($this->config['connections'][$name])) {
return $this->config['connections'][$name];
}

throw new \InvalidArgumentException(\sprintf('Connection `%s` is not defined.', $name));
return $this->config['clients'][$name] ?? throw new \InvalidArgumentException(
"Temporal client config `{$name}` is not defined.",
);
}

/**
* Get default connection address.
*
* @deprecated
*/
public function getAddress(): string
{
return $this->getConnection($this->getDefaultConnection())->address;
return $this->getClientConfig($this->getDefaultClient())->connection->address;
}

/**
Expand All @@ -111,8 +130,18 @@ public function getInterceptors(): array
return $this->config['interceptors'] ?? [];
}

/**
* Get default client options.
*
* @deprecated
*/
public function getClientOptions(): ClientOptions
{
return $this->config['clientOptions'] ?? (new ClientOptions())->withNamespace($this->getTemporalNamespace());
$client = $this->getDefaultClient();
return match(true) {
isset($this->config['clients'][$client]) => $this->config['clients'][$client]->options,
isset($this->config['clientOptions']) => $this->config['clientOptions'],
default => (new ClientOptions())->withNamespace($this->getTemporalNamespace()),
};
}
}
26 changes: 11 additions & 15 deletions tests/app/config/temporal.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,20 @@

declare(strict_types=1);

use Spiral\TemporalBridge\Config\ClientConfig;
use Spiral\TemporalBridge\Config\ConnectionConfig;

return [
'connection' => env('TEMPORAL_CONNECTION', 'default'),
'connections' => [
'default' => ConnectionConfig::create(
address: 'localhost:7233',
),
'ssl' => ConnectionConfig::create(address: 'ssl:7233')
->withTls(
rootCerts: '/path/to/crt',
privateKey: '/path/to/clientKey',
certChain: '/path/to/clientPem',
),
'temporal_cloud' => ConnectionConfig::createCloud(
address: 'ssl:7233',
privateKey: '/path/to/clientKey',
certChain: '/path/to/clientPem',
'client' => env('TEMPORAL_CONNECTION', 'default'),
'clients' => [
'default' => ClientConfig::new(ConnectionConfig::new('localhost:7233')),
'ssl' => ClientConfig::new(
ConnectionConfig::new(address: 'ssl:7233')
->withTls(
rootCerts: '/path/to/crt',
privateKey: '/path/to/clientKey',
certChain: '/path/to/clientPem',
)
),
],
];
2 changes: 1 addition & 1 deletion tests/src/Bootloader/TemporalBridgeBootloaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public function testSecureConnection(): void
public function testNonExistsConnection(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Connection `test` is not defined.');
$this->expectExceptionMessage('Temporal client config `test` is not defined.');

$this->getContainer()->get(ServiceClientInterface::class);
}
Expand Down
Loading

0 comments on commit 38b4118

Please sign in to comment.