@featbit/js-client-sdk 3.0.13 → 4.0.0

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 (120) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +301 -301
  3. package/dist/esm/FbClientCore.d.ts +6 -5
  4. package/dist/esm/FbClientCore.d.ts.map +1 -1
  5. package/dist/esm/FbClientCore.js +27 -4
  6. package/dist/esm/FbClientCore.js.map +1 -1
  7. package/dist/esm/IFbClientCore.d.ts +8 -7
  8. package/dist/esm/IFbClientCore.d.ts.map +1 -1
  9. package/dist/esm/version.d.ts +1 -1
  10. package/dist/esm/version.d.ts.map +1 -1
  11. package/dist/esm/version.js +1 -1
  12. package/dist/esm/version.js.map +1 -1
  13. package/dist/umd/featbit-js-client-sdk-4.0.0.js +2 -0
  14. package/dist/umd/featbit-js-client-sdk-4.0.0.js.map +1 -0
  15. package/dist/umd/featbit-js-client-sdk.js +1 -1
  16. package/dist/umd/featbit-js-client-sdk.js.map +1 -1
  17. package/package.json +46 -46
  18. package/src/Configuration.ts +232 -232
  19. package/src/Context.ts +61 -61
  20. package/src/FbClientBuilder.ts +167 -167
  21. package/src/FbClientCore.ts +428 -405
  22. package/src/IContextProperty.ts +3 -3
  23. package/src/IDataKind.ts +11 -11
  24. package/src/IFbClient.ts +29 -29
  25. package/src/IFbClientCore.ts +291 -290
  26. package/src/IVersionedData.ts +18 -18
  27. package/src/bootstrap/IBootstrapProvider.ts +4 -4
  28. package/src/bootstrap/JsonBootstrapProvider.ts +34 -34
  29. package/src/bootstrap/NullBootstrapProvider.ts +20 -20
  30. package/src/bootstrap/index.ts +2 -2
  31. package/src/constants.ts +1 -1
  32. package/src/data-sources/DataSourceUpdates.ts +116 -116
  33. package/src/data-sources/createStreamListeners.ts +67 -67
  34. package/src/data-sources/index.ts +1 -1
  35. package/src/data-sync/DataSyncMode.ts +3 -3
  36. package/src/data-sync/IDataSynchronizer.ts +15 -15
  37. package/src/data-sync/IRequestor.ts +10 -10
  38. package/src/data-sync/NullDataSynchronizer.ts +14 -14
  39. package/src/data-sync/PollingDataSynchronizer.ts +125 -125
  40. package/src/data-sync/Requestor.ts +61 -61
  41. package/src/data-sync/WebSocketDataSynchronizer.ts +77 -77
  42. package/src/data-sync/index.ts +8 -8
  43. package/src/data-sync/types.ts +19 -19
  44. package/src/data-sync/utils.ts +31 -31
  45. package/src/errors.ts +47 -47
  46. package/src/evaluation/EvalResult.ts +35 -35
  47. package/src/evaluation/Evaluator.ts +26 -26
  48. package/src/evaluation/IEvalDetail.ts +23 -23
  49. package/src/evaluation/ReasonKinds.ts +9 -9
  50. package/src/evaluation/data/IFlag.ts +29 -29
  51. package/src/evaluation/index.ts +4 -4
  52. package/src/events/DefaultEventProcessor.ts +83 -83
  53. package/src/events/DefaultEventQueue.ts +49 -49
  54. package/src/events/DefaultEventSender.ts +73 -73
  55. package/src/events/DefaultEventSerializer.ts +11 -11
  56. package/src/events/EventDispatcher.ts +127 -127
  57. package/src/events/EventSerializer.ts +4 -4
  58. package/src/events/IEventProcessor.ts +8 -8
  59. package/src/events/IEventQueue.ts +16 -16
  60. package/src/events/IEventSender.ts +13 -13
  61. package/src/events/NullEventProcessor.ts +15 -15
  62. package/src/events/event.ts +129 -129
  63. package/src/events/index.ts +11 -11
  64. package/src/index.ts +21 -21
  65. package/src/integrations/TestLogger.ts +24 -24
  66. package/src/integrations/index.ts +1 -1
  67. package/src/integrations/test_data/FlagBuilder.ts +59 -59
  68. package/src/integrations/test_data/TestData.ts +57 -57
  69. package/src/integrations/test_data/TestDataSynchronizer.ts +49 -49
  70. package/src/integrations/test_data/index.ts +4 -4
  71. package/src/logging/BasicLogger.ts +108 -108
  72. package/src/logging/IBasicLoggerOptions.ts +46 -46
  73. package/src/logging/ILogger.ts +49 -49
  74. package/src/logging/LogLevel.ts +8 -8
  75. package/src/logging/SafeLogger.ts +69 -69
  76. package/src/logging/format.ts +154 -154
  77. package/src/logging/index.ts +5 -5
  78. package/src/options/ClientContext.ts +39 -39
  79. package/src/options/IClientContext.ts +53 -53
  80. package/src/options/IOptions.ts +123 -123
  81. package/src/options/IUser.ts +6 -6
  82. package/src/options/IValidatedOptions.ts +29 -29
  83. package/src/options/OptionMessages.ts +35 -35
  84. package/src/options/UserBuilder.ts +35 -35
  85. package/src/options/Validators.ts +300 -300
  86. package/src/options/index.ts +7 -7
  87. package/src/platform/IInfo.ts +102 -102
  88. package/src/platform/IPlatform.ts +20 -20
  89. package/src/platform/IStore.ts +112 -112
  90. package/src/platform/IWebSocket.ts +22 -22
  91. package/src/platform/browser/BrowserInfo.ts +24 -24
  92. package/src/platform/browser/BrowserPlatform.ts +19 -19
  93. package/src/platform/browser/BrowserRequests.ts +6 -6
  94. package/src/platform/browser/BrowserWebSocket.ts +147 -147
  95. package/src/platform/browser/FbClient.ts +65 -65
  96. package/src/platform/browser/LocalStorageStore.ts +59 -59
  97. package/src/platform/index.ts +11 -11
  98. package/src/platform/requests.ts +76 -76
  99. package/src/store/BaseStore.ts +125 -125
  100. package/src/store/DataKinds.ts +6 -6
  101. package/src/store/IDataSourceUpdates.ts +68 -68
  102. package/src/store/InMemoryStore.ts +36 -36
  103. package/src/store/index.ts +5 -5
  104. package/src/store/serialization.ts +52 -52
  105. package/src/store/store.ts +37 -37
  106. package/src/utils/Emits.ts +75 -75
  107. package/src/utils/EventEmitter.ts +128 -128
  108. package/src/utils/IEventEmitter.ts +14 -14
  109. package/src/utils/Regex.ts +21 -21
  110. package/src/utils/ValueConverters.ts +55 -55
  111. package/src/utils/canonicalizeUri.ts +3 -3
  112. package/src/utils/debounce.ts +33 -33
  113. package/src/utils/http.ts +40 -40
  114. package/src/utils/index.ts +5 -5
  115. package/src/utils/isNullOrUndefined.ts +2 -2
  116. package/src/utils/serializeUser.ts +27 -27
  117. package/src/utils/sleep.ts +5 -5
  118. package/src/version.ts +1 -1
  119. package/dist/umd/featbit-js-client-sdk-3.0.13.js +0 -2
  120. package/dist/umd/featbit-js-client-sdk-3.0.13.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
  }