@@ -10,35 +10,43 @@ import type {
1010 RtcConfiguration ,
1111} from '@livekit/rtc-node' ;
1212import { ParticipantKind , RoomEvent , TrackKind } from '@livekit/rtc-node' ;
13+ import { AsyncLocalStorage } from 'node:async_hooks' ;
1314import type { Logger } from 'pino' ;
1415import type { InferenceExecutor } from './ipc/inference_executor.js' ;
1516import { log } from './log.js' ;
1617
17- export class CurrentJobContext {
18- static #current: JobContext ;
19-
20- constructor ( proc : JobContext ) {
21- CurrentJobContext . #current = proc ;
22- }
23-
24- static getCurrent ( ) : JobContext {
25- return CurrentJobContext . #current;
26- }
27- }
18+ // AsyncLocalStorage for job context, similar to Python's contextvars
19+ const jobContextStorage = new AsyncLocalStorage < JobContext > ( ) ;
2820
2921/**
3022 * Returns the current job context.
3123 *
3224 * @throws {Error } if no job context is found
3325 */
3426export function getJobContext ( ) : JobContext {
35- const ctx = CurrentJobContext . getCurrent ( ) ;
27+ const ctx = jobContextStorage . getStore ( ) ;
3628 if ( ! ctx ) {
3729 throw new Error ( 'no job context found, are you running this code inside a job entrypoint?' ) ;
3830 }
3931 return ctx ;
4032}
4133
34+ /**
35+ * Runs a function within a job context, similar to Python's contextvars.
36+ * @internal
37+ */
38+ export function runWithJobContext < T > ( context : JobContext , fn : ( ) => T ) : T {
39+ return jobContextStorage . run ( context , fn ) ;
40+ }
41+
42+ /**
43+ * Runs an async function within a job context, similar to Python's contextvars.
44+ * @internal
45+ */
46+ export function runWithJobContextAsync < T > ( context : JobContext , fn : ( ) => Promise < T > ) : Promise < T > {
47+ return jobContextStorage . run ( context , fn ) ;
48+ }
49+
4250/** Which tracks, if any, should the agent automatically subscribe to? */
4351export enum AutoSubscribe {
4452 SUBSCRIBE_ALL ,
@@ -89,6 +97,8 @@ export class JobContext {
8997 #logger: Logger ;
9098 #inferenceExecutor: InferenceExecutor ;
9199
100+ private connected : boolean = false ;
101+
92102 constructor (
93103 proc : JobProcess ,
94104 info : RunningJobInfo ,
@@ -191,6 +201,10 @@ export class JobContext {
191201 autoSubscribe : AutoSubscribe = AutoSubscribe . SUBSCRIBE_ALL ,
192202 rtcConfig ?: RtcConfiguration ,
193203 ) {
204+ if ( this . connected ) {
205+ return ;
206+ }
207+
194208 const opts = {
195209 e2ee,
196210 autoSubscribe : autoSubscribe == AutoSubscribe . SUBSCRIBE_ALL ,
@@ -215,6 +229,7 @@ export class JobContext {
215229 } ) ;
216230 } ) ;
217231 }
232+ this . connected = true ;
218233 }
219234
220235 /**
0 commit comments