@@ -11,7 +11,7 @@ import {
1111} from "@fluidframework/container-definitions/internal" ;
1212import {
1313 ContainerRuntime ,
14- loadContainerRuntime ,
14+ loadContainerRuntimeAlpha ,
1515 type IContainerRuntimeOptionsInternal ,
1616} from "@fluidframework/container-runtime/internal" ;
1717// eslint-disable-next-line import-x/no-deprecated
@@ -301,6 +301,15 @@ export class DefaultStressDataObject extends StressDataObject {
301301
302302 private stageControls : StageControlsAlpha | undefined ;
303303 private readonly containerRuntimeExp = asLegacyAlpha ( this . context . containerRuntime ) ;
304+
305+ /**
306+ * Sets the stage controls. This is called by the runtime factory when loading
307+ * from pending state that was in staging mode.
308+ */
309+ public setStageControls ( controls : StageControlsAlpha | undefined ) : void {
310+ this . stageControls = controls ;
311+ }
312+
304313 public enterStagingMode ( ) : void {
305314 assert (
306315 this . containerRuntimeExp . enterStagingMode !== undefined ,
@@ -314,12 +323,7 @@ export class DefaultStressDataObject extends StressDataObject {
314323 }
315324
316325 public exitStagingMode ( commit : boolean ) : void {
317- // If stageControls is undefined but we're in staging mode, this means
318- // the container was rehydrated from pending state while in staging mode.
319- // We can't exit staging mode from here - skip gracefully.
320- if ( this . stageControls === undefined ) {
321- return ;
322- }
326+ assert ( this . stageControls !== undefined , "must have staging mode controls" ) ;
323327 if ( commit ) {
324328 this . stageControls . commitChanges ( ) ;
325329 } else {
@@ -355,7 +359,11 @@ export const createRuntimeFactory = (): IRuntimeFactory => {
355359 return this ;
356360 } ,
357361 instantiateRuntime : async ( context , existing ) => {
358- const runtime = await loadContainerRuntime ( {
362+ // Capture stageControls to pass to the entrypoint after loading.
363+ // This must be inside instantiateRuntime so each container instance has its own variable.
364+ let pendingStageControls : StageControlsAlpha | undefined ;
365+
366+ const { runtime, stageControls } = await loadContainerRuntimeAlpha ( {
359367 context,
360368 existing,
361369 runtimeOptions,
@@ -372,9 +380,22 @@ export const createRuntimeFactory = (): IRuntimeFactory => {
372380 ) ;
373381 assert ( aliasedDefault !== undefined , "default must exist" ) ;
374382
375- return aliasedDefault . get ( ) ;
383+ const entryPoint = await aliasedDefault . get ( ) ;
384+
385+ // Pass the stageControls (if any) to the DefaultStressDataObject
386+ // so it can properly exit staging mode when rehydrated from pending state
387+ const maybe : FluidObject < DefaultStressDataObject > | undefined = entryPoint ;
388+ if ( maybe ?. DefaultStressDataObject !== undefined && pendingStageControls !== undefined ) {
389+ maybe . DefaultStressDataObject . setStageControls ( pendingStageControls ) ;
390+ }
391+
392+ return entryPoint ;
376393 } ,
377394 } ) ;
395+
396+ // Store stageControls so it can be passed to entrypoint when getEntryPoint() is called
397+ pendingStageControls = stageControls ;
398+
378399 // id compressor isn't made available via the interface right now.
379400 // We could revisit exposing the safe part of its API (IIdCompressor, not IIdCompressorCore) in a way
380401 // that would avoid this instanceof check, but most customers shouldn't really have a need for it.
0 commit comments