@featbit/js-client-sdk 3.0.11 → 3.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +301 -301
  3. package/dist/esm/FbClientCore.d.ts.map +1 -1
  4. package/dist/esm/FbClientCore.js +1 -1
  5. package/dist/esm/FbClientCore.js.map +1 -1
  6. package/dist/esm/data-sources/DataSourceUpdates.d.ts +2 -2
  7. package/dist/esm/data-sources/DataSourceUpdates.d.ts.map +1 -1
  8. package/dist/esm/data-sources/DataSourceUpdates.js +55 -51
  9. package/dist/esm/data-sources/DataSourceUpdates.js.map +1 -1
  10. package/dist/esm/data-sources/createStreamListeners.d.ts +0 -9
  11. package/dist/esm/data-sources/createStreamListeners.d.ts.map +1 -1
  12. package/dist/esm/data-sources/createStreamListeners.js +10 -10
  13. package/dist/esm/data-sources/createStreamListeners.js.map +1 -1
  14. package/dist/esm/data-sync/IDataSynchronizer.d.ts +1 -1
  15. package/dist/esm/data-sync/IDataSynchronizer.d.ts.map +1 -1
  16. package/dist/esm/data-sync/NullDataSynchronizer.d.ts +1 -1
  17. package/dist/esm/data-sync/NullDataSynchronizer.d.ts.map +1 -1
  18. package/dist/esm/data-sync/NullDataSynchronizer.js +11 -0
  19. package/dist/esm/data-sync/NullDataSynchronizer.js.map +1 -1
  20. package/dist/esm/data-sync/PollingDataSynchronizer.d.ts +1 -1
  21. package/dist/esm/data-sync/PollingDataSynchronizer.d.ts.map +1 -1
  22. package/dist/esm/data-sync/PollingDataSynchronizer.js +42 -17
  23. package/dist/esm/data-sync/PollingDataSynchronizer.js.map +1 -1
  24. package/dist/esm/data-sync/WebSocketDataSynchronizer.d.ts +2 -1
  25. package/dist/esm/data-sync/WebSocketDataSynchronizer.d.ts.map +1 -1
  26. package/dist/esm/data-sync/WebSocketDataSynchronizer.js +20 -6
  27. package/dist/esm/data-sync/WebSocketDataSynchronizer.js.map +1 -1
  28. package/dist/esm/data-sync/types.d.ts +1 -1
  29. package/dist/esm/data-sync/types.d.ts.map +1 -1
  30. package/dist/esm/integrations/test_data/TestDataSynchronizer.d.ts +1 -1
  31. package/dist/esm/integrations/test_data/TestDataSynchronizer.d.ts.map +1 -1
  32. package/dist/esm/integrations/test_data/TestDataSynchronizer.js +3 -1
  33. package/dist/esm/integrations/test_data/TestDataSynchronizer.js.map +1 -1
  34. package/dist/esm/platform/browser/BrowserWebSocket.d.ts.map +1 -1
  35. package/dist/esm/platform/browser/BrowserWebSocket.js +4 -0
  36. package/dist/esm/platform/browser/BrowserWebSocket.js.map +1 -1
  37. package/dist/esm/store/IDataSourceUpdates.d.ts +2 -2
  38. package/dist/esm/store/IDataSourceUpdates.d.ts.map +1 -1
  39. package/dist/esm/version.d.ts +1 -1
  40. package/dist/esm/version.js +1 -1
  41. package/dist/umd/{featbit-js-client-sdk-3.0.11.js → featbit-js-client-sdk-3.0.13.js} +2 -2
  42. package/dist/umd/featbit-js-client-sdk-3.0.13.js.map +1 -0
  43. package/dist/umd/featbit-js-client-sdk.js +1 -1
  44. package/dist/umd/featbit-js-client-sdk.js.map +1 -1
  45. package/package.json +46 -46
  46. package/src/Configuration.ts +232 -232
  47. package/src/Context.ts +61 -61
  48. package/src/FbClientBuilder.ts +167 -167
  49. package/src/FbClientCore.ts +405 -401
  50. package/src/IContextProperty.ts +3 -3
  51. package/src/IDataKind.ts +11 -11
  52. package/src/IFbClient.ts +29 -29
  53. package/src/IFbClientCore.ts +290 -290
  54. package/src/IVersionedData.ts +18 -18
  55. package/src/bootstrap/IBootstrapProvider.ts +4 -4
  56. package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
  57. package/src/bootstrap/NullBootstrapProvider.ts +20 -20
  58. package/src/bootstrap/index.ts +2 -2
  59. package/src/constants.ts +1 -1
  60. package/src/data-sources/DataSourceUpdates.ts +116 -116
  61. package/src/data-sources/createStreamListeners.ts +67 -66
  62. package/src/data-sources/index.ts +1 -1
  63. package/src/data-sync/DataSyncMode.ts +3 -3
  64. package/src/data-sync/IDataSynchronizer.ts +15 -15
  65. package/src/data-sync/IRequestor.ts +10 -10
  66. package/src/data-sync/NullDataSynchronizer.ts +14 -14
  67. package/src/data-sync/PollingDataSynchronizer.ts +125 -111
  68. package/src/data-sync/Requestor.ts +61 -61
  69. package/src/data-sync/WebSocketDataSynchronizer.ts +77 -73
  70. package/src/data-sync/index.ts +8 -8
  71. package/src/data-sync/types.ts +19 -19
  72. package/src/data-sync/utils.ts +31 -31
  73. package/src/errors.ts +47 -47
  74. package/src/evaluation/EvalResult.ts +35 -35
  75. package/src/evaluation/Evaluator.ts +26 -26
  76. package/src/evaluation/IEvalDetail.ts +23 -23
  77. package/src/evaluation/ReasonKinds.ts +9 -9
  78. package/src/evaluation/data/IFlag.ts +29 -29
  79. package/src/evaluation/index.ts +4 -4
  80. package/src/events/DefaultEventProcessor.ts +83 -83
  81. package/src/events/DefaultEventQueue.ts +49 -49
  82. package/src/events/DefaultEventSender.ts +73 -73
  83. package/src/events/DefaultEventSerializer.ts +11 -11
  84. package/src/events/EventDispatcher.ts +127 -127
  85. package/src/events/EventSerializer.ts +4 -4
  86. package/src/events/IEventProcessor.ts +8 -8
  87. package/src/events/IEventQueue.ts +16 -16
  88. package/src/events/IEventSender.ts +13 -13
  89. package/src/events/NullEventProcessor.ts +15 -15
  90. package/src/events/event.ts +129 -129
  91. package/src/events/index.ts +11 -11
  92. package/src/index.ts +21 -21
  93. package/src/integrations/TestLogger.ts +24 -24
  94. package/src/integrations/index.ts +1 -1
  95. package/src/integrations/test_data/FlagBuilder.ts +59 -59
  96. package/src/integrations/test_data/TestData.ts +57 -57
  97. package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
  98. package/src/integrations/test_data/index.ts +4 -4
  99. package/src/logging/BasicLogger.ts +108 -108
  100. package/src/logging/IBasicLoggerOptions.ts +46 -46
  101. package/src/logging/ILogger.ts +49 -49
  102. package/src/logging/LogLevel.ts +8 -8
  103. package/src/logging/SafeLogger.ts +69 -69
  104. package/src/logging/format.ts +154 -154
  105. package/src/logging/index.ts +5 -5
  106. package/src/options/ClientContext.ts +39 -39
  107. package/src/options/IClientContext.ts +53 -53
  108. package/src/options/IOptions.ts +123 -123
  109. package/src/options/IUser.ts +6 -6
  110. package/src/options/IValidatedOptions.ts +29 -29
  111. package/src/options/OptionMessages.ts +35 -35
  112. package/src/options/UserBuilder.ts +35 -35
  113. package/src/options/Validators.ts +300 -300
  114. package/src/options/index.ts +7 -7
  115. package/src/platform/IInfo.ts +102 -102
  116. package/src/platform/IPlatform.ts +20 -20
  117. package/src/platform/IStore.ts +112 -112
  118. package/src/platform/IWebSocket.ts +22 -22
  119. package/src/platform/browser/BrowserInfo.ts +24 -24
  120. package/src/platform/browser/BrowserPlatform.ts +19 -19
  121. package/src/platform/browser/BrowserRequests.ts +6 -6
  122. package/src/platform/browser/BrowserWebSocket.ts +147 -142
  123. package/src/platform/browser/FbClient.ts +65 -65
  124. package/src/platform/browser/LocalStorageStore.ts +59 -59
  125. package/src/platform/index.ts +11 -11
  126. package/src/platform/requests.ts +76 -76
  127. package/src/store/BaseStore.ts +125 -125
  128. package/src/store/DataKinds.ts +6 -6
  129. package/src/store/IDataSourceUpdates.ts +68 -68
  130. package/src/store/InMemoryStore.ts +36 -36
  131. package/src/store/index.ts +5 -5
  132. package/src/store/serialization.ts +52 -52
  133. package/src/store/store.ts +37 -37
  134. package/src/utils/Emits.ts +75 -75
  135. package/src/utils/EventEmitter.ts +128 -128
  136. package/src/utils/IEventEmitter.ts +14 -14
  137. package/src/utils/Regex.ts +21 -21
  138. package/src/utils/ValueConverters.ts +55 -55
  139. package/src/utils/canonicalizeUri.ts +3 -3
  140. package/src/utils/debounce.ts +33 -33
  141. package/src/utils/http.ts +40 -40
  142. package/src/utils/index.ts +5 -5
  143. package/src/utils/isNullOrUndefined.ts +2 -2
  144. package/src/utils/serializeUser.ts +27 -27
  145. package/src/utils/sleep.ts +5 -5
  146. package/src/version.ts +1 -1
  147. package/dist/umd/featbit-js-client-sdk-3.0.11.js.map +0 -1
package/src/errors.ts CHANGED
@@ -1,48 +1,48 @@
1
- export class PollingError extends Error {
2
- public readonly status?: number;
3
-
4
- constructor(message: string, status?: number) {
5
- super(message);
6
- this.status = status;
7
- this.name = 'FbPollingError';
8
- }
9
- }
10
-
11
- export class StreamingError extends Error {
12
- public readonly code?: number;
13
-
14
- constructor(message: string, code?: number) {
15
- super(message);
16
- this.code = code;
17
- this.name = 'FbStreamingError';
18
- }
19
- }
20
-
21
- export class UnexpectedResponseError extends Error {
22
- constructor(message: string) {
23
- super(message);
24
- this.name = 'FbUnexpectedResponseError';
25
- }
26
- }
27
-
28
-
29
- export class ClientError extends Error {
30
- constructor(message: string) {
31
- super(message);
32
- this.name = 'FbClientError';
33
- }
34
- }
35
-
36
- export class TimeoutError extends Error {
37
- constructor(message: string) {
38
- super(message);
39
- this.name = 'FeatBitTimeoutError';
40
- }
41
- }
42
-
43
- export function isHttpRecoverable(status: number) {
44
- if (status >= 400 && status < 500) {
45
- return status === 400 || status === 408 || status === 429;
46
- }
47
- return true;
1
+ export class PollingError extends Error {
2
+ public readonly status?: number;
3
+
4
+ constructor(message: string, status?: number) {
5
+ super(message);
6
+ this.status = status;
7
+ this.name = 'FbPollingError';
8
+ }
9
+ }
10
+
11
+ export class StreamingError extends Error {
12
+ public readonly code?: number;
13
+
14
+ constructor(message: string, code?: number) {
15
+ super(message);
16
+ this.code = code;
17
+ this.name = 'FbStreamingError';
18
+ }
19
+ }
20
+
21
+ export class UnexpectedResponseError extends Error {
22
+ constructor(message: string) {
23
+ super(message);
24
+ this.name = 'FbUnexpectedResponseError';
25
+ }
26
+ }
27
+
28
+
29
+ export class ClientError extends Error {
30
+ constructor(message: string) {
31
+ super(message);
32
+ this.name = 'FbClientError';
33
+ }
34
+ }
35
+
36
+ export class TimeoutError extends Error {
37
+ constructor(message: string) {
38
+ super(message);
39
+ this.name = 'FeatBitTimeoutError';
40
+ }
41
+ }
42
+
43
+ export function isHttpRecoverable(status: number) {
44
+ if (status >= 400 && status < 500) {
45
+ return status === 400 || status === 408 || status === 429;
46
+ }
47
+ return true;
48
48
  }
@@ -1,36 +1,36 @@
1
- import { ReasonKinds } from "./ReasonKinds";
2
- import { IFlag } from "./data/IFlag";
3
- import { EvalEvent } from "../events/event";
4
- import { IUser } from "../options/IUser";
5
-
6
- /**
7
- * A class which encapsulates the result of an evaluation. It allows for differentiating between
8
- * successful and error result types.
9
- *
10
- * @internal
11
- */
12
- export default class EvalResult {
13
- protected constructor(
14
- public kind: ReasonKinds,
15
- public value: IFlag | null,
16
- public reason?: string,
17
- ) {
18
- }
19
-
20
- static flagNotFound(flagKey: string) {
21
- return new EvalResult(ReasonKinds.FlagNotFound, null, `flag not found: ${ flagKey }`);
22
- }
23
-
24
- static matched(val: IFlag) {
25
- return new EvalResult(ReasonKinds.Match, val, 'target match');
26
- }
27
-
28
- toEvalEvent(user: IUser): EvalEvent | null {
29
- if (this.kind !== ReasonKinds.Match) {
30
- return null;
31
- }
32
-
33
- const targetedVariation = this.value?.variations.find(v => v.value === this.value?.variation);
34
- return new EvalEvent(user, this.value?.id!, targetedVariation!, this.value?.sendToExperiment!);
35
- }
1
+ import { ReasonKinds } from "./ReasonKinds";
2
+ import { IFlag } from "./data/IFlag";
3
+ import { EvalEvent } from "../events/event";
4
+ import { IUser } from "../options/IUser";
5
+
6
+ /**
7
+ * A class which encapsulates the result of an evaluation. It allows for differentiating between
8
+ * successful and error result types.
9
+ *
10
+ * @internal
11
+ */
12
+ export default class EvalResult {
13
+ protected constructor(
14
+ public kind: ReasonKinds,
15
+ public value: IFlag | null,
16
+ public reason?: string,
17
+ ) {
18
+ }
19
+
20
+ static flagNotFound(flagKey: string) {
21
+ return new EvalResult(ReasonKinds.FlagNotFound, null, `flag not found: ${ flagKey }`);
22
+ }
23
+
24
+ static matched(val: IFlag) {
25
+ return new EvalResult(ReasonKinds.Match, val, 'target match');
26
+ }
27
+
28
+ toEvalEvent(user: IUser): EvalEvent | null {
29
+ if (this.kind !== ReasonKinds.Match) {
30
+ return null;
31
+ }
32
+
33
+ const targetedVariation = this.value?.variations.find(v => v.value === this.value?.variation);
34
+ return new EvalEvent(user, this.value?.id!, targetedVariation!, this.value?.sendToExperiment!);
35
+ }
36
36
  }
@@ -1,27 +1,27 @@
1
- import { IFlag } from "./data/IFlag";
2
- import EvalResult from "./EvalResult";
3
- import { IStore } from "../platform/IStore";
4
- import DataKinds from "../store/DataKinds";
5
-
6
- /**
7
- * @internal
8
- */
9
- export default class Evaluator {
10
- constructor(private store: IStore) {
11
- }
12
-
13
- /**
14
- * Evaluate the given flag against the given context.
15
- * @param flagKey The key of the feature flag.
16
- */
17
- evaluate(
18
- flagKey: string,
19
- ): EvalResult {
20
- const flag = this.store.get(DataKinds.Flags, flagKey) as unknown as IFlag;
21
- if (!flag) {
22
- return EvalResult.flagNotFound(flagKey);
23
- }
24
-
25
- return EvalResult.matched(flag);
26
- }
1
+ import { IFlag } from "./data/IFlag";
2
+ import EvalResult from "./EvalResult";
3
+ import { IStore } from "../platform/IStore";
4
+ import DataKinds from "../store/DataKinds";
5
+
6
+ /**
7
+ * @internal
8
+ */
9
+ export default class Evaluator {
10
+ constructor(private store: IStore) {
11
+ }
12
+
13
+ /**
14
+ * Evaluate the given flag against the given context.
15
+ * @param flagKey The key of the feature flag.
16
+ */
17
+ evaluate(
18
+ flagKey: string,
19
+ ): EvalResult {
20
+ const flag = this.store.get(DataKinds.Flags, flagKey) as unknown as IFlag;
21
+ if (!flag) {
22
+ return EvalResult.flagNotFound(flagKey);
23
+ }
24
+
25
+ return EvalResult.matched(flag);
26
+ }
27
27
  }
@@ -1,24 +1,24 @@
1
- import { ReasonKinds } from "./ReasonKinds";
2
-
3
- export interface IEvalDetail<TValue> {
4
- /**
5
- * The unique key of the feature flag.
6
- */
7
- flagKey: string;
8
-
9
- /**
10
- * An enum indicating the category of the reason. See {@link ReasonKinds}
11
- */
12
- kind: ReasonKinds;
13
-
14
- /**
15
- * The result of the flag evaluation. This will be either one of the flag's variations or
16
- * the default value that was passed to `FbClient.variationDetail`.
17
- */
18
- value?: TValue;
19
-
20
- /**
21
- * A string describing the main factor that influenced the flag evaluation value.
22
- */
23
- reason?: string;
1
+ import { ReasonKinds } from "./ReasonKinds";
2
+
3
+ export interface IEvalDetail<TValue> {
4
+ /**
5
+ * The unique key of the feature flag.
6
+ */
7
+ flagKey: string;
8
+
9
+ /**
10
+ * An enum indicating the category of the reason. See {@link ReasonKinds}
11
+ */
12
+ kind: ReasonKinds;
13
+
14
+ /**
15
+ * The result of the flag evaluation. This will be either one of the flag's variations or
16
+ * the default value that was passed to `FbClient.variationDetail`.
17
+ */
18
+ value?: TValue;
19
+
20
+ /**
21
+ * A string describing the main factor that influenced the flag evaluation value.
22
+ */
23
+ reason?: string;
24
24
  }
@@ -1,10 +1,10 @@
1
- /**
2
- * Different kinds of error which may be encountered during evaluation.
3
- */
4
- export enum ReasonKinds {
5
- ClientNotReady = 'ClientNotReady',
6
- Match = 'Match',
7
- WrongType = 'WrongType',
8
- FlagNotFound = 'FlagNotFound',
9
- Error = 'Error'
1
+ /**
2
+ * Different kinds of error which may be encountered during evaluation.
3
+ */
4
+ export enum ReasonKinds {
5
+ ClientNotReady = 'ClientNotReady',
6
+ Match = 'Match',
7
+ WrongType = 'WrongType',
8
+ FlagNotFound = 'FlagNotFound',
9
+ Error = 'Error'
10
10
  }
@@ -1,29 +1,29 @@
1
- export type FlagValue = any;
2
-
3
- export enum VariationDataType {
4
- string = 'string',
5
- boolean = 'boolean',
6
- number = 'number',
7
- json = 'json',
8
- empty = ''
9
- }
10
-
11
- export interface IVariation {
12
- id: number,
13
- value: FlagValue
14
- }
15
-
16
- export interface IFlagBase {
17
- id: string, // the key
18
- variation: FlagValue,
19
- variationType: VariationDataType,
20
- sendToExperiment?: boolean,
21
- timestamp?: number,
22
- variationOptions?: IVariation[],
23
- }
24
-
25
- export interface IFlag extends IFlagBase {
26
- key: string, // the same value to id
27
- variations: IVariation[],// the same value to variationOptions
28
- version: number
29
- }
1
+ export type FlagValue = any;
2
+
3
+ export enum VariationDataType {
4
+ string = 'string',
5
+ boolean = 'boolean',
6
+ number = 'number',
7
+ json = 'json',
8
+ empty = ''
9
+ }
10
+
11
+ export interface IVariation {
12
+ id: number,
13
+ value: FlagValue
14
+ }
15
+
16
+ export interface IFlagBase {
17
+ id: string, // the key
18
+ variation: FlagValue,
19
+ variationType: VariationDataType,
20
+ sendToExperiment?: boolean,
21
+ timestamp?: number,
22
+ variationOptions?: IVariation[],
23
+ }
24
+
25
+ export interface IFlag extends IFlagBase {
26
+ key: string, // the same value to id
27
+ variations: IVariation[],// the same value to variationOptions
28
+ version: number
29
+ }
@@ -1,5 +1,5 @@
1
- export * from './data';
2
- export * from './EvalResult';
3
- export * from './Evaluator';
4
- export * from './IEvalDetail';
1
+ export * from './data';
2
+ export * from './EvalResult';
3
+ export * from './Evaluator';
4
+ export * from './IEvalDetail';
5
5
  export * from './ReasonKinds';
@@ -1,84 +1,84 @@
1
- import { IEventProcessor } from "./IEventProcessor";
2
- import { EventDispatcher } from "./EventDispatcher";
3
- import ClientContext from "../options/ClientContext";
4
- import { FlushEvent, IEvent, ShutdownEvent } from "./event";
5
- import { isNullOrUndefined } from "../utils/isNullOrUndefined";
6
- import { IEventQueue } from "./IEventQueue";
7
- import { DefaultEventQueue } from "./DefaultEventQueue";
8
- import { ILogger } from "../logging/ILogger";
9
-
10
- export class DefaultEventProcessor implements IEventProcessor {
11
- private readonly logger: ILogger;
12
- private readonly flushInterval: number;
13
- private readonly eventDispatcher: EventDispatcher;
14
- private readonly eventQueue: IEventQueue;
15
- private closed: boolean = false;
16
-
17
- constructor(clientContext: ClientContext) {
18
- const {logger, flushInterval, maxEventsInQueue} = clientContext;
19
- this.logger = logger!;
20
- this.flushInterval = flushInterval;
21
- this.eventQueue = new DefaultEventQueue(maxEventsInQueue, this.logger);
22
- this.eventDispatcher = new EventDispatcher(clientContext, this.eventQueue);
23
-
24
- this.flushLoop();
25
- }
26
-
27
- private flushLoop() {
28
- if (this.closed) {
29
- return;
30
- }
31
-
32
- setTimeout(async () => {
33
- try {
34
- await this.flush();
35
- } catch (err) {
36
- this.logger.error('Unexpected error while flushing events in event processor.', err);
37
- }
38
-
39
- this.flushLoop();
40
- }, this.flushInterval);
41
- }
42
-
43
- flush(): Promise<any> {
44
- const flushEvent = new FlushEvent();
45
- this.record(flushEvent);
46
- return flushEvent.waitForCompletion();
47
- }
48
-
49
- async close(): Promise<void> {
50
- if (this.closed) {
51
- return;
52
- }
53
-
54
- // send a shutdown event to dispatcher
55
- const shutdown = new ShutdownEvent();
56
- this.record(shutdown);
57
-
58
- try {
59
- await shutdown.waitForCompletion();
60
- } catch (err) {
61
- this.logger.error('Event processor shutdown but not complete.');
62
- }
63
-
64
- // mark the event queue as complete for adding
65
- this.eventQueue.close();
66
- this.closed = true;
67
- }
68
-
69
- record(event: IEvent | null): boolean {
70
- if (isNullOrUndefined(event)) {
71
- return false;
72
- }
73
-
74
- if (!this.eventQueue.addEvent(event!)) {
75
- if (event instanceof FlushEvent) {
76
- event.complete();
77
- }
78
-
79
- return false;
80
- }
81
-
82
- return true;
83
- }
1
+ import { IEventProcessor } from "./IEventProcessor";
2
+ import { EventDispatcher } from "./EventDispatcher";
3
+ import ClientContext from "../options/ClientContext";
4
+ import { FlushEvent, IEvent, ShutdownEvent } from "./event";
5
+ import { isNullOrUndefined } from "../utils/isNullOrUndefined";
6
+ import { IEventQueue } from "./IEventQueue";
7
+ import { DefaultEventQueue } from "./DefaultEventQueue";
8
+ import { ILogger } from "../logging/ILogger";
9
+
10
+ export class DefaultEventProcessor implements IEventProcessor {
11
+ private readonly logger: ILogger;
12
+ private readonly flushInterval: number;
13
+ private readonly eventDispatcher: EventDispatcher;
14
+ private readonly eventQueue: IEventQueue;
15
+ private closed: boolean = false;
16
+
17
+ constructor(clientContext: ClientContext) {
18
+ const {logger, flushInterval, maxEventsInQueue} = clientContext;
19
+ this.logger = logger!;
20
+ this.flushInterval = flushInterval;
21
+ this.eventQueue = new DefaultEventQueue(maxEventsInQueue, this.logger);
22
+ this.eventDispatcher = new EventDispatcher(clientContext, this.eventQueue);
23
+
24
+ this.flushLoop();
25
+ }
26
+
27
+ private flushLoop() {
28
+ if (this.closed) {
29
+ return;
30
+ }
31
+
32
+ setTimeout(async () => {
33
+ try {
34
+ await this.flush();
35
+ } catch (err) {
36
+ this.logger.error('Unexpected error while flushing events in event processor.', err);
37
+ }
38
+
39
+ this.flushLoop();
40
+ }, this.flushInterval);
41
+ }
42
+
43
+ flush(): Promise<any> {
44
+ const flushEvent = new FlushEvent();
45
+ this.record(flushEvent);
46
+ return flushEvent.waitForCompletion();
47
+ }
48
+
49
+ async close(): Promise<void> {
50
+ if (this.closed) {
51
+ return;
52
+ }
53
+
54
+ // send a shutdown event to dispatcher
55
+ const shutdown = new ShutdownEvent();
56
+ this.record(shutdown);
57
+
58
+ try {
59
+ await shutdown.waitForCompletion();
60
+ } catch (err) {
61
+ this.logger.error('Event processor shutdown but not complete.');
62
+ }
63
+
64
+ // mark the event queue as complete for adding
65
+ this.eventQueue.close();
66
+ this.closed = true;
67
+ }
68
+
69
+ record(event: IEvent | null): boolean {
70
+ if (isNullOrUndefined(event)) {
71
+ return false;
72
+ }
73
+
74
+ if (!this.eventQueue.addEvent(event!)) {
75
+ if (event instanceof FlushEvent) {
76
+ event.complete();
77
+ }
78
+
79
+ return false;
80
+ }
81
+
82
+ return true;
83
+ }
84
84
  }
@@ -1,50 +1,50 @@
1
- import { IEventQueue } from "./IEventQueue";
2
- import { IEvent } from "./event";
3
- import { ILogger } from "../logging/ILogger";
4
-
5
- export class DefaultEventQueue implements IEventQueue {
6
- private events: IEvent[];
7
- private closed: boolean = false;
8
-
9
- constructor(private readonly capacity: number, private readonly logger: ILogger) {
10
- this.events = [];
11
- }
12
-
13
- addEvent(event: IEvent): boolean {
14
- if (this.closed) {
15
- return false;
16
- }
17
-
18
- if (this.events.length >= this.capacity) {
19
- this.logger.warn("Events are being produced faster than they can be processed. We shouldn't see this.");
20
- return false;
21
- }
22
-
23
- this.events.push(event);
24
- return true;
25
- }
26
-
27
- clear(): void {
28
- this.events = [];
29
- }
30
-
31
- shift(): IEvent | undefined {
32
- return this.events.shift();
33
- }
34
-
35
- close(): void {
36
- this.closed = true;
37
- }
38
-
39
- get eventsSnapshot(): IEvent[] {
40
- return [...this.events];
41
- }
42
-
43
- get length(): number {
44
- return this.events.length;
45
- }
46
-
47
- get isEmpty(): boolean {
48
- return this.length === 0;
49
- }
1
+ import { IEventQueue } from "./IEventQueue";
2
+ import { IEvent } from "./event";
3
+ import { ILogger } from "../logging/ILogger";
4
+
5
+ export class DefaultEventQueue implements IEventQueue {
6
+ private events: IEvent[];
7
+ private closed: boolean = false;
8
+
9
+ constructor(private readonly capacity: number, private readonly logger: ILogger) {
10
+ this.events = [];
11
+ }
12
+
13
+ addEvent(event: IEvent): boolean {
14
+ if (this.closed) {
15
+ return false;
16
+ }
17
+
18
+ if (this.events.length >= this.capacity) {
19
+ this.logger.warn("Events are being produced faster than they can be processed. We shouldn't see this.");
20
+ return false;
21
+ }
22
+
23
+ this.events.push(event);
24
+ return true;
25
+ }
26
+
27
+ clear(): void {
28
+ this.events = [];
29
+ }
30
+
31
+ shift(): IEvent | undefined {
32
+ return this.events.shift();
33
+ }
34
+
35
+ close(): void {
36
+ this.closed = true;
37
+ }
38
+
39
+ get eventsSnapshot(): IEvent[] {
40
+ return [...this.events];
41
+ }
42
+
43
+ get length(): number {
44
+ return this.events.length;
45
+ }
46
+
47
+ get isEmpty(): boolean {
48
+ return this.length === 0;
49
+ }
50
50
  }