@@ -1347,6 +1347,56 @@ pub async fn unity_execute_code(project_path: &str, code: &str) -> Result<String
13471347 unity_execute_code_with_progress ( project_path, code, |_| { } ) . await
13481348}
13491349
1350+ async fn wait_for_unity_bridge_ready_after_recompile ( project_path : & str ) -> Result < ( ) , String > {
1351+ let max_wait = Duration :: from_secs ( 30 ) ;
1352+ let start = std:: time:: Instant :: now ( ) ;
1353+
1354+ loop {
1355+ let detail =
1356+ match send_message_with_timeout ( project_path, "status" , "" , Duration :: from_secs ( 5 ) )
1357+ . await
1358+ {
1359+ Ok ( resp) if resp. ok => return Ok ( ( ) ) ,
1360+ Ok ( resp) => resp
1361+ . error
1362+ . unwrap_or_else ( || "Unity status returned ok=false" . to_string ( ) ) ,
1363+ Err ( error) => error,
1364+ } ;
1365+
1366+ if start. elapsed ( ) > max_wait {
1367+ return Err ( format ! (
1368+ "Timed out waiting for Unity bridge to become ready after recompile (30s): {}" ,
1369+ detail
1370+ ) ) ;
1371+ }
1372+
1373+ tokio:: time:: sleep ( Duration :: from_millis ( 500 ) ) . await ;
1374+ }
1375+ }
1376+
1377+ async fn refresh_unity_type_index_after_recompile ( project_path : & str ) -> Result < ( ) , String > {
1378+ const MAX_ATTEMPTS : u32 = 3 ;
1379+ let mut last_error = String :: new ( ) ;
1380+
1381+ for attempt in 1 ..=MAX_ATTEMPTS {
1382+ match refresh_unity_type_index ( project_path) . await {
1383+ Ok ( _) => return Ok ( ( ) ) ,
1384+ Err ( error) => {
1385+ last_error = error;
1386+ eprintln ! (
1387+ "[Locus] Unity type index refresh after recompile attempt {}/{} failed: {}" ,
1388+ attempt, MAX_ATTEMPTS , last_error
1389+ ) ;
1390+ if attempt < MAX_ATTEMPTS {
1391+ tokio:: time:: sleep ( Duration :: from_secs ( 1 ) ) . await ;
1392+ }
1393+ }
1394+ }
1395+ }
1396+
1397+ Err ( last_error)
1398+ }
1399+
13501400/// Trigger a Unity recompile and wait until the new domain is ready.
13511401///
13521402/// Flow:
@@ -1376,7 +1426,10 @@ pub async fn recompile_and_wait(project_path: &str) -> Result<String, String> {
13761426 ) ;
13771427 }
13781428
1379- let resp = send_message ( project_path, "request_recompile" , "" ) . await ?;
1429+ let resp = match send_message ( project_path, "request_recompile" , "" ) . await {
1430+ Ok ( resp) => resp,
1431+ Err ( error) => return finish ( Err ( error) ) ,
1432+ } ;
13801433 if !resp. ok {
13811434 return finish ( Err ( resp
13821435 . error
@@ -1400,12 +1453,13 @@ pub async fn recompile_and_wait(project_path: &str) -> Result<String, String> {
14001453 Ok ( resp) if resp. ok => {
14011454 eprintln ! ( "[Locus] Unity reconnected after domain reload" ) ;
14021455 crate :: unity_type_index:: invalidate_cached_type_index ( project_path) . await ;
1403- transport:: disconnect_with_reason (
1404- project_path,
1405- "Unity reconnected after domain reload" ,
1406- )
1407- . await ;
1408- if let Err ( error) = refresh_unity_type_index ( project_path) . await {
1456+ if let Err ( error) =
1457+ wait_for_unity_bridge_ready_after_recompile ( project_path) . await
1458+ {
1459+ return finish ( Err ( error) ) ;
1460+ }
1461+ if let Err ( error) = refresh_unity_type_index_after_recompile ( project_path) . await
1462+ {
14091463 eprintln ! (
14101464 "[Locus] Unity type index refresh after recompile skipped: {}" ,
14111465 error
@@ -1429,12 +1483,14 @@ pub async fn recompile_and_wait(project_path: &str) -> Result<String, String> {
14291483 "ok" => {
14301484 crate :: unity_type_index:: invalidate_cached_type_index ( project_path)
14311485 . await ;
1432- transport:: disconnect_with_reason (
1433- project_path,
1434- "Unity recompile completed" ,
1435- )
1436- . await ;
1437- if let Err ( error) = refresh_unity_type_index ( project_path) . await {
1486+ if let Err ( error) =
1487+ wait_for_unity_bridge_ready_after_recompile ( project_path) . await
1488+ {
1489+ return finish ( Err ( error) ) ;
1490+ }
1491+ if let Err ( error) =
1492+ refresh_unity_type_index_after_recompile ( project_path) . await
1493+ {
14381494 eprintln ! (
14391495 "[Locus] Unity type index refresh after recompile skipped: {}" ,
14401496 error
0 commit comments