1
+ import { AbortController , anySignal } from '../../common/AbortController' ;
1
2
import { IdGenerator } from '../../common/IdGenerator' ;
2
3
import { TimeHelper } from '../../common/TimeHelper' ;
3
4
import { BacktraceAttachment } from '../../model/attachment' ;
@@ -18,6 +19,12 @@ export class BacktraceDatabase implements BacktraceModule {
18
19
return this . _enabled ;
19
20
}
20
21
22
+ /**
23
+ * Abort controller to cancel asynchronous database operations when
24
+ * the database is being disabled by the user.
25
+ */
26
+ private readonly _abortController = new AbortController ( ) ;
27
+
21
28
private readonly _databaseRecordContext : BacktraceDatabaseContext ;
22
29
private readonly _storageProviders : BacktraceDatabaseStorageProvider [ ] = [ ] ;
23
30
@@ -158,6 +165,7 @@ export class BacktraceDatabase implements BacktraceModule {
158
165
public dispose ( ) {
159
166
this . _enabled = false ;
160
167
clearInterval ( this . _intervalId ) ;
168
+ this . _abortController . abort ( ) ;
161
169
}
162
170
163
171
/**
@@ -188,30 +196,40 @@ export class BacktraceDatabase implements BacktraceModule {
188
196
/**
189
197
* Sends all records available in the database to Backtrace and removes them
190
198
* no matter if the submission process was successful or not.
199
+ * @param abortSignal optional abort signal to cancel sending requests
191
200
*/
192
- public async flush ( ) {
201
+ public async flush ( abortSignal ?: AbortSignal ) {
193
202
const start = TimeHelper . now ( ) ;
194
- await this . send ( ) ;
203
+ await this . send ( abortSignal ) ;
195
204
const records = this . get ( ) . filter ( ( n ) => n . timestamp <= start ) ;
196
205
for ( const record of records ) {
206
+ if ( abortSignal ?. aborted ) {
207
+ return ;
208
+ }
197
209
this . remove ( record ) ;
198
210
}
199
211
}
212
+
200
213
/**
201
214
* Sends all records available in the database to Backtrace.
215
+ * @param abortSignal optional abort signal to cancel sending requests
202
216
*/
203
- public async send ( ) {
217
+ public async send ( abortSignal ?: AbortSignal ) {
204
218
for ( let bucketIndex = 0 ; bucketIndex < this . _databaseRecordContext . bucketCount ; bucketIndex ++ ) {
205
219
// make a copy of records to not update the array after each remove
206
220
const records = [ ...this . _databaseRecordContext . getBucket ( bucketIndex ) ] ;
221
+ const signal = anySignal ( abortSignal , this . _abortController . signal ) ;
207
222
208
223
for ( const record of records ) {
224
+ if ( ! this . enabled ) {
225
+ return ;
226
+ }
209
227
if ( record . locked ) {
210
228
continue ;
211
229
}
212
230
try {
213
231
record . locked = true ;
214
- const result = await this . _requestHandler . send ( record . data , record . attachments ) ;
232
+ const result = await this . _requestHandler . send ( record . data , record . attachments , signal ) ;
215
233
if ( result . status === 'Ok' ) {
216
234
this . remove ( record ) ;
217
235
continue ;
0 commit comments