Skip to content

Commit ff7afae

Browse files
authored
Add standalone event publisher (#537)
1 parent 2655f24 commit ff7afae

8 files changed

Lines changed: 1015 additions & 99 deletions

File tree

‎src/channel/httpBeaconChannel.ts‎

Lines changed: 49 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ import type {Logger} from '../logging';
55
import {NullLogger} from '../logging';
66
import type {CidAssigner} from '../cid';
77
import {formatMessage} from '../error';
8-
import type {ApiProblem} from '../error';
9-
import {CLIENT_LIBRARY} from '../constants';
108
import {Help} from '../help';
9+
import type {EventPublisher, PublishRequest} from '../eventPublisher';
10+
import {PublishError} from '../eventPublisher';
1111

1212
export type Configuration = {
13-
appId: string,
14-
endpointUrl: string,
13+
publisher: EventPublisher,
1514
cidAssigner: CidAssigner,
1615
logger?: Logger,
1716
};
1817

18+
/**
19+
* @deprecated Use `PublishErrorType` from the `eventPublisher` module instead.
20+
*/
1921
export enum TrackingErrorType {
2022
SUSPENDED_SERVICE = 'https://croct.help/sdk/javascript/suspended-service',
2123
// Server errors
@@ -41,70 +43,50 @@ export class HttpBeaconChannel implements DuplexChannel<string, Envelope<string,
4143
return Promise.reject(MessageDeliveryError.nonRetryable('Channel is closed'));
4244
}
4345

44-
const {token, timestamp, context, payload} = JSON.parse(message);
45-
const {endpointUrl, appId, cidAssigner} = this.configuration;
46-
47-
return fetch(endpointUrl, {
48-
method: 'POST',
49-
headers: {
50-
'X-App-Id': appId,
51-
'X-Client-Id': await cidAssigner.assignCid(),
52-
'X-Client-Library': CLIENT_LIBRARY,
53-
'Content-Type': 'application/json',
54-
...(token !== undefined ? {'X-Token': token} : {}),
55-
},
56-
body: JSON.stringify({
57-
context: context,
58-
payload: payload,
59-
originalTime: timestamp,
60-
departureTime: Date.now(),
61-
}),
62-
keepalive: true,
63-
}).then(async response => {
64-
if (response.ok) {
65-
if (response.status === 202) {
66-
this.logger.warn(
67-
'Event tracking is currently suspended for this application, check the workspace settings. '
68-
+ `For help, see ${TrackingErrorType.SUSPENDED_SERVICE}`,
46+
const {token, timestamp, context, payload: {type, ...payload}} = JSON.parse(message);
47+
const {publisher, cidAssigner} = this.configuration;
48+
49+
const request: PublishRequest = {
50+
type: type,
51+
payload: payload,
52+
clientId: await cidAssigner.assignCid(),
53+
timestamp: timestamp,
54+
context: context,
55+
userToken: token,
56+
};
57+
58+
return publisher.publish(request, {extra: {keepalive: true}})
59+
.then(
60+
() => this.notify(receiptId),
61+
(error: unknown) => {
62+
if (!(error instanceof PublishError)) {
63+
throw error;
64+
}
65+
66+
const problem = error.response;
67+
const isRetryable = HttpBeaconChannel.isRetryable(problem.status);
68+
69+
// The publisher already logs the help for known problems
70+
if (!isRetryable && Help.forApiProblem(problem) === undefined) {
71+
this.logger.error(`Beacon rejected with non-retryable status: ${problem.title}`);
72+
}
73+
74+
return Promise.reject(
75+
isRetryable
76+
? MessageDeliveryError.retryable(problem.title)
77+
: MessageDeliveryError.nonRetryable(problem.title),
6978
);
70-
}
71-
72-
this.notify(receiptId);
73-
74-
return;
75-
}
76-
77-
const problem: ApiProblem = await response.json().catch(
78-
() => ({
79-
type: TrackingErrorType.INTERNAL_ERROR,
80-
title: response.statusText,
81-
status: response.status,
82-
}),
83-
);
84-
85-
const isRetryable = HttpBeaconChannel.isRetryable(problem.status);
86-
const help = Help.forApiProblem(problem);
87-
88-
if (help !== undefined) {
89-
this.logger.error(help);
90-
} else if (!isRetryable) {
91-
this.logger.error(`Beacon rejected with non-retryable status: ${problem.title}`);
92-
}
93-
94-
return Promise.reject(
95-
isRetryable
96-
? MessageDeliveryError.retryable(problem.title)
97-
: MessageDeliveryError.nonRetryable(problem.title),
98-
);
99-
}).catch(error => {
100-
this.logger.error(`Failed to publish beacon: ${formatMessage(error)}`);
101-
102-
return Promise.reject(
103-
error instanceof MessageDeliveryError
104-
? error
105-
: MessageDeliveryError.retryable(error),
106-
);
107-
});
79+
},
80+
)
81+
.catch(error => {
82+
this.logger.error(`Failed to publish beacon: ${formatMessage(error)}`);
83+
84+
return Promise.reject(
85+
error instanceof MessageDeliveryError
86+
? error
87+
: MessageDeliveryError.retryable(error),
88+
);
89+
});
10890
}
10991

11092
public subscribe(listener: ChannelListener<string>): void {

‎src/container.ts‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type {CookieCacheConfiguration} from './cache/cookieCache';
2626
import {CookieCache} from './cache/cookieCache';
2727
import {FilteredLogger} from './logging/filteredLogger';
2828
import {HttpBeaconChannel} from './channel/httpBeaconChannel';
29+
import {EventPublisher} from './eventPublisher';
2930
import {DeduplicatedLogger} from './logging/deduplicatedLogger';
3031

3132
export type Configuration = {
@@ -36,7 +37,7 @@ export type Configuration = {
3637
test: boolean,
3738
disableCidMirroring: boolean,
3839
cidAssignerEndpointUrl: string,
39-
trackerEndpointUrl: string,
40+
trackerBaseEndpointUrl: string,
4041
evaluationBaseEndpointUrl: string,
4142
contentBaseEndpointUrl: string,
4243
beaconQueueSize: number,
@@ -235,14 +236,17 @@ export class Container {
235236
}
236237

237238
const channelLogger = this.getLogger('BeaconChannel');
238-
const {appId, trackerEndpointUrl} = this.configuration;
239+
const {appId, trackerBaseEndpointUrl} = this.configuration;
239240

240241
const queuedChannel = new QueuedChannel(
241242
new RetryChannel({
242243
channel: new GuaranteedChannel({
243244
channel: new HttpBeaconChannel({
244-
appId: appId,
245-
endpointUrl: trackerEndpointUrl,
245+
publisher: new EventPublisher({
246+
appId: appId,
247+
baseEndpointUrl: trackerBaseEndpointUrl,
248+
logger: channelLogger,
249+
}),
246250
cidAssigner: this.getCidAssigner(),
247251
logger: channelLogger,
248252
}),

0 commit comments

Comments
 (0)