@@ -384,6 +384,92 @@ describe("buildGatewayCronService", () => {
384384 }
385385 } ) ;
386386
387+ it ( "routes global-scope main cron jobs through the global queue for queued wakes" , async ( ) => {
388+ const cfg = {
389+ ...createCronConfig ( "server-cron-global-queued" ) ,
390+ session : { mainKey : "main" , scope : "global" } ,
391+ } as OpenClawConfig ;
392+ loadConfigMock . mockReturnValue ( cfg ) ;
393+
394+ const state = buildGatewayCronService ( {
395+ cfg,
396+ deps : { } as CliDeps ,
397+ broadcast : ( ) => { } ,
398+ } ) ;
399+ try {
400+ const job = await state . cron . add ( {
401+ name : "global-queued" ,
402+ enabled : true ,
403+ schedule : { kind : "at" , at : new Date ( 1 ) . toISOString ( ) } ,
404+ sessionTarget : "main" ,
405+ wakeMode : "next-heartbeat" ,
406+ payload : { kind : "systemEvent" , text : "hello global" } ,
407+ } ) ;
408+
409+ await state . cron . run ( job . id , "force" ) ;
410+
411+ expect ( callArg ( enqueueSystemEventMock , 0 , 0 , "system event text" ) ) . toBe ( "hello global" ) ;
412+ const eventOptions = requireRecord (
413+ callArg ( enqueueSystemEventMock , 0 , 1 , "system event options" ) ,
414+ "options" ,
415+ ) ;
416+ expect ( eventOptions . sessionKey ) . toBe ( "global" ) ;
417+ const heartbeatRequest = requireRecord (
418+ callArg ( requestHeartbeatMock , 0 , 0 , "heartbeat request" ) ,
419+ "request" ,
420+ ) ;
421+ expect ( heartbeatRequest . agentId ) . toBe ( "main" ) ;
422+ expect ( heartbeatRequest . sessionKey ) . toBe ( "global" ) ;
423+ } finally {
424+ state . cron . stop ( ) ;
425+ }
426+ } ) ;
427+
428+ it ( "routes global-scope immediate main cron jobs through the global heartbeat lane" , async ( ) => {
429+ const cfg = {
430+ ...createCronConfig ( "server-cron-global-now" ) ,
431+ session : { mainKey : "main" , scope : "global" } ,
432+ } as OpenClawConfig ;
433+ loadConfigMock . mockReturnValue ( cfg ) ;
434+
435+ const state = buildGatewayCronService ( {
436+ cfg,
437+ deps : { } as CliDeps ,
438+ broadcast : ( ) => { } ,
439+ } ) ;
440+ try {
441+ const job = await state . cron . add ( {
442+ name : "global-now" ,
443+ enabled : true ,
444+ schedule : { kind : "at" , at : new Date ( 1 ) . toISOString ( ) } ,
445+ sessionTarget : "main" ,
446+ wakeMode : "now" ,
447+ payload : { kind : "systemEvent" , text : "hello now" } ,
448+ } ) ;
449+
450+ await state . cron . run ( job . id , "force" ) ;
451+
452+ const eventOptions = requireRecord (
453+ callArg ( enqueueSystemEventMock , 0 , 1 , "system event options" ) ,
454+ "options" ,
455+ ) ;
456+ expect ( eventOptions . sessionKey ) . toBe ( "global" ) ;
457+ const heartbeatRun = requireRecord (
458+ callArg ( runHeartbeatOnceMock , 0 , 0 , "heartbeat run options" ) ,
459+ "heartbeat run options" ,
460+ ) ;
461+ expect ( heartbeatRun . agentId ) . toBe ( "main" ) ;
462+ expect ( heartbeatRun . sessionKey ) . toBe ( "global" ) ;
463+ expect ( heartbeatRun . heartbeat ) . toEqual ( {
464+ target : "last" ,
465+ to : undefined ,
466+ accountId : undefined ,
467+ } ) ;
468+ } finally {
469+ state . cron . stop ( ) ;
470+ }
471+ } ) ;
472+
387473 it ( "forwards heartbeat overrides through the cron wake adapter" , ( ) => {
388474 const cfg = createCronConfig ( "server-cron-heartbeat-override" ) ;
389475 loadConfigMock . mockReturnValue ( cfg ) ;
0 commit comments