77from transformerlab .services import job_service , quota_service
88from transformerlab .services .provider_service import get_provider_by_id , get_provider_instance
99from transformerlab .db .session import async_session
10+ from transformerlab .shared .request_context import set_current_org_id
11+ from lab import dirs as lab_dirs
1012
1113
1214class LocalLaunchWorkItem (BaseModel ):
@@ -15,6 +17,7 @@ class LocalLaunchWorkItem(BaseModel):
1517 job_id : str
1618 experiment_id : str
1719 provider_id : str
20+ team_id : str
1821 cluster_name : str
1922 cluster_config : ClusterConfig
2023 quota_hold_id : Optional [str ] = None
@@ -30,6 +33,7 @@ async def enqueue_local_launch(
3033 job_id : str ,
3134 experiment_id : str ,
3235 provider_id : str ,
36+ team_id : str ,
3337 cluster_name : str ,
3438 cluster_config : ClusterConfig ,
3539 quota_hold_id : Optional [str ],
@@ -42,6 +46,7 @@ async def enqueue_local_launch(
4246 job_id = str (job_id ),
4347 experiment_id = str (experiment_id ),
4448 provider_id = str (provider_id ),
49+ team_id = str (team_id ),
4550 cluster_name = cluster_name ,
4651 cluster_config = cluster_config ,
4752 quota_hold_id = quota_hold_id ,
@@ -62,71 +67,81 @@ async def _local_launch_worker() -> None:
6267 try :
6368 # Use a dedicated DB session inside the worker
6469 async with async_session () as session :
65- provider = await get_provider_by_id (session , item .provider_id )
66- if not provider :
67- await job_service .job_update_status (
68- item .job_id ,
69- "FAILED" ,
70- experiment_id = item .experiment_id ,
71- error_msg = "Provider not found for local launch" ,
72- session = session ,
73- )
74- if item .quota_hold_id :
75- await quota_service .release_quota_hold (session , hold_id = item .quota_hold_id )
76- await session .commit ()
77- continue
78-
79- provider_instance = await get_provider_instance (provider )
80-
81- # Transition from WAITING -> initial_status (LAUNCHING / INTERACTIVE)
82- await job_service .job_update_status (
83- item .job_id ,
84- item .initial_status ,
85- experiment_id = item .experiment_id ,
86- session = session ,
87- )
88- await session .commit ()
89-
90- loop = asyncio .get_running_loop ()
70+ # Ensure lab SDK and API request context are scoped to the correct organization
71+ set_current_org_id (item .team_id )
72+ lab_dirs .set_organization_id (item .team_id )
9173 try :
92- # Ensure only one local launch runs at a time
93- async with _worker_lock :
94- launch_result = await loop .run_in_executor (
95- None ,
96- lambda : provider_instance .launch_cluster (item .cluster_name , item .cluster_config ),
74+ provider = await get_provider_by_id (session , item .provider_id )
75+ if not provider :
76+ await job_service .job_update_status (
77+ item .job_id ,
78+ "FAILED" ,
79+ experiment_id = item .experiment_id ,
80+ error_msg = "Provider not found for local launch" ,
81+ session = session ,
9782 )
98- except Exception as exc : # noqa: BLE001
99- # Release quota hold and mark job failed
100- if item .quota_hold_id :
101- await quota_service .release_quota_hold (session , hold_id = item .quota_hold_id )
102- await session .commit ()
83+ if item .quota_hold_id :
84+ await quota_service .release_quota_hold (session , hold_id = item .quota_hold_id )
85+ await session .commit ()
86+ continue
87+
88+ provider_instance = await get_provider_instance (provider )
10389
90+ # Transition from WAITING -> initial_status (LAUNCHING / INTERACTIVE)
10491 await job_service .job_update_status (
10592 item .job_id ,
106- "FAILED" ,
93+ item . initial_status ,
10794 experiment_id = item .experiment_id ,
108- error_msg = str (exc ),
10995 session = session ,
11096 )
11197 await session .commit ()
112- continue
11398
114- # On success, we keep the job in LAUNCHING/INTERACTIVE; status checks will
115- # complete it when the local process exits.
116- if isinstance (launch_result , dict ):
117- await job_service .job_update_job_data_insert_key_value (
118- item .job_id ,
119- "provider_launch_result" ,
120- launch_result ,
121- item .experiment_id ,
122- )
123- request_id = launch_result .get ("request_id" )
124- if request_id :
99+ loop = asyncio .get_running_loop ()
100+ try :
101+ # Ensure only one local launch runs at a time
102+ async with _worker_lock :
103+ launch_result = await loop .run_in_executor (
104+ None ,
105+ lambda : provider_instance .launch_cluster (item .cluster_name , item .cluster_config ),
106+ )
107+ except Exception as exc : # noqa: BLE001
108+ # Release quota hold and mark job failed
109+ if item .quota_hold_id :
110+ await quota_service .release_quota_hold (session , hold_id = item .quota_hold_id )
111+ await session .commit ()
112+
113+ await job_service .job_update_status (
114+ item .job_id ,
115+ "FAILED" ,
116+ experiment_id = item .experiment_id ,
117+ error_msg = str (exc ),
118+ session = session ,
119+ )
120+ await session .commit ()
121+ continue
122+
123+ print (f"DEBUG: LocalProviderQueue._local_launch_worker: launch_result={ launch_result } " )
124+
125+ # On success, we keep the job in LAUNCHING/INTERACTIVE; status checks will
126+ # complete it when the local process exits.
127+ if isinstance (launch_result , dict ):
125128 await job_service .job_update_job_data_insert_key_value (
126129 item .job_id ,
127- "orchestrator_request_id " ,
128- request_id ,
130+ "provider_launch_result " ,
131+ launch_result ,
129132 item .experiment_id ,
130133 )
134+ request_id = launch_result .get ("request_id" )
135+ if request_id :
136+ await job_service .job_update_job_data_insert_key_value (
137+ item .job_id ,
138+ "orchestrator_request_id" ,
139+ request_id ,
140+ item .experiment_id ,
141+ )
142+ finally :
143+ # Clear org context after each item
144+ set_current_org_id (None )
145+ lab_dirs .set_organization_id (None )
131146 finally :
132147 _local_launch_queue .task_done ()
0 commit comments