|
| 1 | +import type { FeatureFlag } from '@sentry/types'; |
| 2 | +import type { FlagBufferInterface } from '@sentry/types/build/types/flags'; |
| 3 | + |
| 4 | +export const DEFAULT_FLAG_BUFFER_SIZE = 100; |
| 5 | + |
| 6 | +/** |
| 7 | + * Array implementation of types/FlagBufferInterface. |
| 8 | + * |
| 9 | + * Ordered LRU cache for storing feature flags in the scope context. The name |
| 10 | + * of each flag in the buffer is unique, and the output of getAll() is ordered |
| 11 | + * from oldest to newest. |
| 12 | + */ |
| 13 | +export class FlagBuffer implements FlagBufferInterface { |
| 14 | + public readonly maxSize: number; |
| 15 | + |
| 16 | + private readonly _flags: FeatureFlag[]; |
| 17 | + |
| 18 | + public constructor(_maxSize: number = DEFAULT_FLAG_BUFFER_SIZE, _initialFlags: FeatureFlag[] = []) { |
| 19 | + this.maxSize = _maxSize; |
| 20 | + if (_initialFlags.length > _maxSize) { |
| 21 | + throw Error(`_initialFlags param exceeds the maxSize of ${_maxSize}`); |
| 22 | + } |
| 23 | + this._flags = _initialFlags; |
| 24 | + } |
| 25 | + |
| 26 | + /** |
| 27 | + * @inheritdoc |
| 28 | + */ |
| 29 | + public clone(): FlagBuffer { |
| 30 | + return new FlagBuffer(this.maxSize, this._flags); |
| 31 | + } |
| 32 | + |
| 33 | + /** |
| 34 | + * @inheritdoc |
| 35 | + */ |
| 36 | + public getAll(): readonly FeatureFlag[] { |
| 37 | + return [...this._flags]; // shallow copy |
| 38 | + } |
| 39 | + |
| 40 | + /** |
| 41 | + * @inheritdoc |
| 42 | + */ |
| 43 | + public insert(name: string, value: boolean): void { |
| 44 | + // Check if the flag is already in the buffer |
| 45 | + const index = this._flags.findIndex(f => f.flag === name); |
| 46 | + |
| 47 | + if (index !== -1) { |
| 48 | + // The flag was found, remove it from its current position - O(n) |
| 49 | + this._flags.splice(index, 1); |
| 50 | + } |
| 51 | + |
| 52 | + if (this._flags.length === this.maxSize) { |
| 53 | + // If at capacity, pop the earliest flag - O(n) |
| 54 | + this._flags.shift(); |
| 55 | + } |
| 56 | + |
| 57 | + // Push the flag to the end - O(1) |
| 58 | + this._flags.push({ |
| 59 | + flag: name, |
| 60 | + result: value, |
| 61 | + }); |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * @inheritdoc |
| 66 | + */ |
| 67 | + public clear(): number { |
| 68 | + const length = this._flags.length; |
| 69 | + this._flags.splice(0, length); // O(n) |
| 70 | + return length; |
| 71 | + } |
| 72 | +} |
0 commit comments