Skip to content

Commit a06bd65

Browse files
authored
Merge pull request #2 from keboola/odin-PS-1306
feat: add client factory
2 parents 424ebe6 + a9ca4b3 commit a06bd65

27 files changed

Lines changed: 649 additions & 137 deletions

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ $client->postEvent(
3333
);
3434
```
3535

36+
or use a factory to create the client
37+
38+
```php
39+
use Keboola\NotificationClient\ClientFactory;
40+
41+
$clientFactory = new ClientFactory('https://connection.keboola.com');
42+
$clientFactory->getEventsClient('xxx-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
43+
```
44+
3645
## Development
3746
- Create an Azure service principal to download the required images and login:
3847

@@ -58,7 +67,7 @@ $client->postEvent(
5867
```
5968

6069
- Set the following environment variables in `set-env.sh` file (use `set-env.template.sh` as sample):
61-
- `STORAGE_API_URL` - Keboola Connection URL.
70+
- `STORAGE_API_URL` - Keboola Connection URL to arbitrary stack where the notification service is registered.
6271
- `TEST_STORAGE_API_TOKEN` - Token to a test project.
6372
- `TEST_MANAGE_API_APPLICATION_TOKEN` - Application token with scope `notifications:push-event`.
6473

azure-pipelines.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ stages:
7070
TEST_STORAGE_API_TOKEN: $(TEST_STORAGE_API_TOKEN)
7171
TEST_MANAGE_API_APPLICATION_TOKEN: $(TEST_MANAGE_API_APPLICATION_TOKEN)
7272
TEST_NOTIFICATION_API_URL: http://$(NOTIFICATION_API_IP):8181
73+
STORAGE_API_URL: $(STORAGE_API_URL)
74+
TEST_STORAGE_API_PROJECT_ID: $(TEST_STORAGE_API_PROJECT_ID)
7375
7476
- task: PublishTestResults@2
7577
displayName: 'Publish Test results'

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ services:
1010
TEST_NOTIFICATION_API_URL:
1111
TEST_STORAGE_API_TOKEN:
1212
TEST_MANAGE_API_APPLICATION_TOKEN:
13+
STORAGE_API_URL:
14+
TEST_STORAGE_API_PROJECT_ID:
1315
command: ['composer', 'ci']
1416

1517
tests-local:

provisioning/environments.yaml.template

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ metadata:
2323
name: dev-notification-environments
2424
namespace: dev-notification-client
2525
data:
26+
appEnv: 'dev'
27+
keboolaStack: 'local'
2628
awsAccessKeyId: '$TEST_AWS_ACCESS_KEY_ID'
2729
awsLogsS3Bucket: '$AWS_LOGS_S3_BUCKET'
2830
awsRegion: '$AWS_REGION'
2931
azureLogsAbsContainer: '$AZURE_LOGS_ABS_CONTAINER'
3032
azureClientId: '$TEST_AZURE_CLIENT_ID'
3133
azureTenantId: '$TEST_AZURE_TENANT_ID'
3234
storageApiUrl: '$STORAGE_API_URL'
33-
mailerUrl: 'null://null'
35+
databaseSslVerifyEnabled: '0'
36+
messengerTransportDsn: 'doctrine://default'
37+
mailerDsn: 'null://null'

provisioning/notification.yaml

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,24 @@ spec:
7272
cpu: "250m"
7373
memory: "256Mi"
7474
ports:
75-
- containerPort: 80
75+
- containerPort: 8080
7676
command:
7777
- "/bin/sh"
7878
args:
7979
- "-c"
8080
- 'php bin/console doctrine:migrations:migrate --no-interaction && apache2-foreground'
8181
env:
82+
- name: APP_ENV
83+
valueFrom:
84+
configMapKeyRef:
85+
name: dev-notification-environments
86+
key: appEnv
87+
- name: KEBOOLA_STACK
88+
valueFrom:
89+
configMapKeyRef:
90+
name: dev-notification-environments
91+
key: keboolaStack
92+
8293
- name: AWS_LOGS_S3_BUCKET
8394
valueFrom:
8495
configMapKeyRef:
@@ -137,34 +148,37 @@ spec:
137148
secretKeyRef:
138149
name: dev-notification-environments
139150
key: databaseUrl
151+
- name: DATABASE_SSL_VERIFY_ENABLED
152+
valueFrom:
153+
configMapKeyRef:
154+
name: dev-notification-environments
155+
key: databaseSslVerifyEnabled
156+
- name: MESSENGER_TRANSPORT_DSN
157+
valueFrom:
158+
configMapKeyRef:
159+
name: dev-notification-environments
160+
key: messengerTransportDsn
140161
- name: MAILER_DSN
141162
valueFrom:
142163
configMapKeyRef:
143164
name: dev-notification-environments
144-
key: mailerUrl
165+
key: mailerDsn
166+
145167

146168
readinessProbe:
147-
httpGet:
148-
path: /health-check
149-
port: 80
150-
httpHeaders:
151-
- name: Host
152-
value: KubernetesReadinessProbe
153-
initialDelaySeconds: 60
154-
periodSeconds: 30
155-
successThreshold: 1
156-
failureThreshold: 3
157-
livenessProbe:
158-
httpGet:
159-
port: 80
160-
path: /health-check
161-
httpHeaders:
162-
- name: Host
163-
value: KubernetesLivelinessProbe
164-
initialDelaySeconds: 60
165-
periodSeconds: 100
166-
successThreshold: 1
167-
failureThreshold:
169+
tcpSocket:
170+
port: 8080
171+
initialDelaySeconds: 15
172+
periodSeconds: 20
173+
# until https://keboola.atlassian.net/browse/PS-2344 is fixed
174+
# httpGet:
175+
# path: /health-check
176+
# port: 8080
177+
# httpHeaders:
178+
# - name: Host
179+
# value: KubernetesReadinessProbe
180+
# initialDelaySeconds: 60
181+
# periodSeconds: 30
168182
---
169183
kind: Service
170184
apiVersion: v1
@@ -177,7 +191,7 @@ spec:
177191
app: dev-notification-api
178192
ports:
179193
- port: 8181
180-
targetPort: 80
194+
targetPort: 8080
181195
protocol: TCP
182196
name: http
183197
---

src/Client.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Psr\Http\Message\RequestInterface;
1818
use Psr\Http\Message\ResponseInterface;
1919
use Psr\Log\LoggerInterface;
20-
use Symfony\Component\Validator\Constraints\NotBlank;
2120
use Symfony\Component\Validator\Constraints\Range;
2221
use Symfony\Component\Validator\Constraints\Url;
2322
use Symfony\Component\Validator\ConstraintViolationInterface;
@@ -32,15 +31,12 @@ abstract class Client
3231
protected GuzzleClient $guzzle;
3332

3433
public function __construct(
35-
string $notificationApiUrl,
36-
string $token,
34+
string $baseUrl,
35+
?string $token,
3736
array $options = []
3837
) {
3938
$validator = Validation::createValidator();
40-
$errors = $validator->validate($notificationApiUrl, [new Url()]);
41-
$errors->addAll(
42-
$validator->validate($token, [new NotBlank()])
43-
);
39+
$errors = $validator->validate($baseUrl, [new Url()]);
4440
if (!empty($options['backoffMaxTries'])) {
4541
$errors->addAll($validator->validate($options['backoffMaxTries'], [new Range(['min' => 0, 'max' => 100])]));
4642
$options['backoffMaxTries'] = intval($options['backoffMaxTries']);
@@ -58,7 +54,7 @@ public function __construct(
5854
}
5955
throw new NotificationClientException('Invalid parameters when creating client: ' . $messages);
6056
}
61-
$this->guzzle = $this->initClient($notificationApiUrl, $token, $options);
57+
$this->guzzle = $this->initClient($baseUrl, $token, $options);
6258
}
6359

6460
private function createDefaultDecider(int $maxRetries): Closure
@@ -79,9 +75,9 @@ private function createDefaultDecider(int $maxRetries): Closure
7975
};
8076
}
8177

82-
abstract protected function getTokenHeaderName(): string;
78+
abstract protected function getTokenHeaderName(): ?string;
8379

84-
private function initClient(string $url, string $token, array $options = []): GuzzleClient
80+
private function initClient(string $url, ?string $token, array $options = []): GuzzleClient
8581
{
8682
// Initialize handlers (start with those supplied in constructor)
8783
$handlerStack = HandlerStack::create($options['handler'] ?? null);
@@ -90,10 +86,13 @@ private function initClient(string $url, string $token, array $options = []): Gu
9086
// Set handler to set default headers
9187
$handlerStack->push(Middleware::mapRequest(
9288
function (RequestInterface $request) use ($token, $options) {
93-
return $request
89+
$request = $request
9490
->withHeader('User-Agent', $options['userAgent'])
95-
->withHeader($this->getTokenHeaderName(), $token)
9691
->withHeader('Content-type', 'application/json');
92+
if ($this->getTokenHeaderName()) {
93+
$request = $request->withHeader((string) $this->getTokenHeaderName(), (string) $token);
94+
}
95+
return $request;
9796
}
9897
));
9998
// Set client logger

src/ClientFactory.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Keboola\NotificationClient;
6+
7+
use Keboola\NotificationClient\Requests\PostEvent\FailedJobEventData;
8+
9+
class ClientFactory
10+
{
11+
private const NOTIFICATION_SERVICE_NAME = 'notification';
12+
private ?string $notificationUrl;
13+
private string $connectionUrl;
14+
private array $connectionClientOptions;
15+
16+
public function __construct(string $connectionUrl, array $connectionClientOptions = [])
17+
{
18+
$this->connectionUrl = $connectionUrl;
19+
$this->connectionClientOptions = $connectionClientOptions;
20+
$this->notificationUrl = null;
21+
}
22+
23+
private function getNotificationUrl(): string
24+
{
25+
if ($this->notificationUrl === null) {
26+
$storageApiIndexClient = new StorageApiIndexClient($this->connectionUrl, $this->connectionClientOptions);
27+
$this->notificationUrl = $storageApiIndexClient->getServiceUrl(self::NOTIFICATION_SERVICE_NAME);
28+
}
29+
return (string) $this->notificationUrl;
30+
}
31+
32+
public function getEventsClient(string $applicationToken, array $options = []): EventsClient
33+
{
34+
return new EventsClient($this->getNotificationUrl(), $applicationToken, $options);
35+
}
36+
37+
public function getSubscriptionClient(string $storageApiToken, array $options = []): SubscriptionClient
38+
{
39+
return new SubscriptionClient($this->getNotificationUrl(), $storageApiToken, $options);
40+
}
41+
}

src/EventsClient.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use JsonException;
99
use Keboola\NotificationClient\Exception\ClientException;
1010
use Keboola\NotificationClient\Requests\Event;
11-
use Psr\Log\LoggerInterface;
1211

1312
class EventsClient extends Client
1413
{
@@ -22,6 +21,12 @@ public function __construct(
2221
string $applicationToken,
2322
array $options = []
2423
) {
24+
if (empty($applicationToken)) {
25+
throw new ClientException(sprintf(
26+
'Application token must be non-empty, %s provided.',
27+
json_encode($applicationToken)
28+
));
29+
}
2530
parent::__construct($notificationApiUrl, $applicationToken, $options);
2631
}
2732

src/Requests/Event.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ class Event implements JsonSerializable
1111
private JsonSerializable $eventData;
1212
private string $eventType;
1313

14-
public function __construct(string $eventType, JsonSerializable $eventData)
14+
public function __construct(EventDataInterface $eventData)
1515
{
16-
$this->eventType = $eventType;
16+
$this->eventType = $eventData::getEventTypeName();
1717
$this->eventData = $eventData;
1818
}
1919

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Keboola\NotificationClient\Requests;
6+
7+
use JsonSerializable;
8+
9+
interface EventDataInterface extends JsonSerializable
10+
{
11+
public static function getEventTypeName(): string;
12+
}

0 commit comments

Comments
 (0)