Skip to content

Commit 6b1a8a3

Browse files
committed
wip
1 parent 1fe4a0f commit 6b1a8a3

File tree

2 files changed

+53
-35
lines changed

2 files changed

+53
-35
lines changed

packages/browser/src/transports/base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
getGlobalObject,
1919
logger,
2020
parseRetryAfterHeader,
21-
PromiseBuffer,
21+
makePromiseBuffer,
2222
SentryError,
2323
} from '@sentry/utils';
2424

packages/utils/src/promisebuffer.ts

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,43 @@ function allPromises<U = unknown>(collection: Array<U | PromiseLike<U>>): Promis
2222
});
2323
}
2424

25-
/** A simple queue that holds promises. */
26-
export class PromiseBuffer<T> {
27-
/** Internal set of queued Promises */
28-
private readonly _buffer: Array<PromiseLike<T>> = [];
25+
interface PromiseBuffer<T> {
26+
_buffer: Array<PromiseLike<T>>;
27+
isReady(): boolean;
28+
add(taskProducer: () => PromiseLike<T>): PromiseLike<T>;
29+
remove(task: PromiseLike<T>): PromiseLike<T>;
30+
length(): number;
31+
drain(timeout?: number): PromiseLike<boolean>;
32+
}
33+
34+
const DEFAULT_BUFFER_LIMIT = 30;
35+
36+
/**
37+
* Create a new promise buffer
38+
* @param limit
39+
*/
40+
export function makePromiseBuffer<T>(limit: number = DEFAULT_BUFFER_LIMIT): PromiseBuffer<T> {
41+
const buffer: Array<PromiseLike<T>> = [];
42+
43+
/**
44+
* This function returns the number of unresolved promises in the queue.
45+
*/
46+
function length(): number {
47+
return buffer.length;
48+
}
2949

30-
public constructor(protected _limit?: number) {}
50+
function isReady(): boolean {
51+
return length() < limit;
52+
}
3153

3254
/**
33-
* Says if the buffer is ready to take more requests
55+
* Remove a promise from the queue.
56+
*
57+
* @param task Can be any PromiseLike<T>
58+
* @returns Removed promise.
3459
*/
35-
public isReady(): boolean {
36-
return this._limit === undefined || this.length() < this._limit;
60+
function remove(task: PromiseLike<T>): PromiseLike<T> {
61+
return buffer.splice(buffer.indexOf(task), 1)[0];
3762
}
3863

3964
/**
@@ -46,47 +71,29 @@ export class PromiseBuffer<T> {
4671
* limit check.
4772
* @returns The original promise.
4873
*/
49-
public add(taskProducer: () => PromiseLike<T>): PromiseLike<T> {
50-
if (!this.isReady()) {
74+
function add(taskProducer: () => PromiseLike<T>): PromiseLike<T> {
75+
if (!isReady()) {
5176
return SyncPromise.reject(new SentryError('Not adding Promise due to buffer limit reached.'));
5277
}
5378

5479
// start the task and add its promise to the queue
5580
const task = taskProducer();
56-
if (this._buffer.indexOf(task) === -1) {
57-
this._buffer.push(task);
81+
if (buffer.indexOf(task) === -1) {
82+
buffer.push(task);
5883
}
5984
void task
60-
.then(() => this.remove(task))
85+
.then(() => remove(task))
6186
// Use `then(null, rejectionHandler)` rather than `catch(rejectionHandler)` so that we can use `PromiseLike`
6287
// rather than `Promise`. `PromiseLike` doesn't have a `.catch` method, making its polyfill smaller. (ES5 didn't
6388
// have promises, so TS has to polyfill when down-compiling.)
6489
.then(null, () =>
65-
this.remove(task).then(null, () => {
90+
remove(task).then(null, () => {
6691
// We have to add another catch here because `this.remove()` starts a new promise chain.
6792
}),
6893
);
6994
return task;
7095
}
7196

72-
/**
73-
* Remove a promise from the queue.
74-
*
75-
* @param task Can be any PromiseLike<T>
76-
* @returns Removed promise.
77-
*/
78-
public remove(task: PromiseLike<T>): PromiseLike<T> {
79-
const removedTask = this._buffer.splice(this._buffer.indexOf(task), 1)[0];
80-
return removedTask;
81-
}
82-
83-
/**
84-
* This function returns the number of unresolved promises in the queue.
85-
*/
86-
public length(): number {
87-
return this._buffer.length;
88-
}
89-
9097
/**
9198
* Wait for all promises in the queue to resolve or for timeout to expire, whichever comes first.
9299
*
@@ -96,7 +103,7 @@ export class PromiseBuffer<T> {
96103
* @returns A promise which will resolve to `true` if the queue is already empty or drains before the timeout, and
97104
* `false` otherwise
98105
*/
99-
public drain(timeout?: number): PromiseLike<boolean> {
106+
function drain(timeout?: number): PromiseLike<boolean> {
100107
return new SyncPromise<boolean>(resolve => {
101108
// wait for `timeout` ms and then resolve to `false` (if not cancelled first)
102109
const capturedSetTimeout = setTimeout(() => {
@@ -106,10 +113,21 @@ export class PromiseBuffer<T> {
106113
}, timeout);
107114

108115
// if all promises resolve in time, cancel the timer and resolve to `true`
109-
void allPromises(this._buffer).then(() => {
116+
void allPromises(buffer).then(() => {
110117
clearTimeout(capturedSetTimeout);
111118
resolve(true);
112119
});
113120
});
114121
}
122+
123+
const promiseBuffer: PromiseBuffer<T> = {
124+
_buffer: buffer,
125+
length,
126+
isReady,
127+
add,
128+
remove,
129+
drain,
130+
};
131+
132+
return promiseBuffer;
115133
}

0 commit comments

Comments
 (0)