@@ -48,6 +48,7 @@ import {
48
48
LazyPromise ,
49
49
PromiseCache ,
50
50
delay ,
51
+ fail ,
51
52
} from "@fluidframework/core-utils/internal" ;
52
53
import type {
53
54
IClientDetails ,
@@ -1266,7 +1267,7 @@ export class ContainerRuntime
1266
1267
private readonly batchRunner = new BatchRunCounter ( ) ;
1267
1268
private readonly _flushMode : FlushMode ;
1268
1269
private readonly offlineEnabled : boolean ;
1269
- private flushTaskExists = false ;
1270
+ private flushScheduled = false ;
1270
1271
1271
1272
private _connected : boolean ;
1272
1273
@@ -2541,6 +2542,7 @@ export class ContainerRuntime
2541
2542
// Since we don't submit ID Allocation ops when staged, any outstanding ranges would be from
2542
2543
// before staging mode so we can simply say staged: false.
2543
2544
this . submitIdAllocationOpIfNeeded ( { resubmitOutstandingRanges : true , staged : false } ) ;
2545
+ this . scheduleFlush ( ) ;
2544
2546
2545
2547
// replay the ops
2546
2548
this . pendingStateManager . replayPendingStates ( ) ;
@@ -3200,6 +3202,8 @@ export class ContainerRuntime
3200
3202
* @param resubmitInfo - If defined, indicates this is a resubmission of a batch with the given Batch info needed for resubmit.
3201
3203
*/
3202
3204
private flush ( resubmitInfo ?: BatchResubmitInfo ) : void {
3205
+ this . flushScheduled = false ;
3206
+
3203
3207
try {
3204
3208
assert (
3205
3209
! this . batchRunner . running ,
@@ -3431,13 +3435,6 @@ export class ContainerRuntime
3431
3435
) ;
3432
3436
}
3433
3437
3434
- /**
3435
- * Typically ops are batched and later flushed together, but in some cases we want to flush immediately.
3436
- */
3437
- private currentlyBatching ( ) : boolean {
3438
- return this . flushMode !== FlushMode . Immediate || this . batchRunner . running ;
3439
- }
3440
-
3441
3438
private readonly _quorum : IQuorumClients ;
3442
3439
public getQuorum ( ) : IQuorumClients {
3443
3440
return this . _quorum ;
@@ -4443,13 +4440,7 @@ export class ContainerRuntime
4443
4440
this . outbox . submit ( message ) ;
4444
4441
}
4445
4442
4446
- // Note: Technically, the system "always" batches - if this case is true we'll just have a single-message batch.
4447
- const flushImmediatelyOnSubmit = ! this . currentlyBatching ( ) ;
4448
- if ( flushImmediatelyOnSubmit ) {
4449
- this . flush ( ) ;
4450
- } else {
4451
- this . scheduleFlush ( ) ;
4452
- }
4443
+ this . scheduleFlush ( ) ;
4453
4444
} catch ( error ) {
4454
4445
const dpe = DataProcessingError . wrapIfUnrecognized ( error , "ContainerRuntime.submit" , {
4455
4446
referenceSequenceNumber : this . deltaManager . lastSequenceNumber ,
@@ -4462,25 +4453,24 @@ export class ContainerRuntime
4462
4453
}
4463
4454
4464
4455
private scheduleFlush ( ) : void {
4465
- if ( this . flushTaskExists ) {
4456
+ if ( this . flushScheduled ) {
4466
4457
return ;
4467
4458
}
4468
-
4469
- this . flushTaskExists = true ;
4470
-
4471
- // TODO: hoist this out of the function scope to save unnecessary allocations
4472
- // eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
4473
- const flush = ( ) : void => {
4474
- this . flushTaskExists = false ;
4475
- this . flush ( ) ;
4476
- } ;
4459
+ this . flushScheduled = true ;
4477
4460
4478
4461
switch ( this . flushMode ) {
4462
+ case FlushMode . Immediate : {
4463
+ // When in Immediate flush mode, flush immediately unless we are intentionally batching multiple ops (e.g. via orderSequentially)
4464
+ if ( ! this . batchRunner . running ) {
4465
+ this . flush ( ) ;
4466
+ }
4467
+ break ;
4468
+ }
4479
4469
case FlushMode . TurnBased : {
4480
4470
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
4481
4471
// batch at the end of the turn
4482
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
4483
- Promise . resolve ( ) . then ( flush ) ;
4472
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises -- Container will close if flush throws
4473
+ Promise . resolve ( ) . then ( ( ) => this . flush ( ) ) ;
4484
4474
break ;
4485
4475
}
4486
4476
@@ -4489,16 +4479,12 @@ export class ContainerRuntime
4489
4479
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
4490
4480
// batch when all micro-tasks are complete.
4491
4481
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
4492
- setTimeout ( flush , 0 ) ;
4482
+ setTimeout ( ( ) => this . flush ( ) , 0 ) ;
4493
4483
break ;
4494
4484
}
4495
4485
4496
4486
default : {
4497
- assert (
4498
- this . batchRunner . running ,
4499
- 0x587 /* Unreachable unless manually accumulating a batch */ ,
4500
- ) ;
4501
- break ;
4487
+ fail ( 0x587 /* Unreachable unless manually accumulating a batch */ ) ;
4502
4488
}
4503
4489
}
4504
4490
}
0 commit comments