@@ -1350,6 +1350,136 @@ fn load_mounted_session_ids_from_conn(conn: &Connection, workspace_id: &str) ->
13501350 . unwrap_or_default ( )
13511351}
13521352
1353+ struct SnapshotBase {
1354+ workspace : WorkspaceSummary ,
1355+ view_state : WorkspaceViewState ,
1356+ visible_session_ids : Vec < String > ,
1357+ terminals : Vec < TerminalInfo > ,
1358+ }
1359+
1360+ fn load_snapshot_base_from_conn (
1361+ conn : & Connection ,
1362+ workspace_id : & str ,
1363+ ) -> Result < SnapshotBase , String > {
1364+ let workspace = row_to_workspace_summary ( load_workspace_row ( conn, workspace_id) ?) ;
1365+ let view_state = match load_view_state_from_conn ( conn, workspace_id) {
1366+ Ok ( value) => value,
1367+ Err ( _) => default_view_state ( DEFAULT_SESSION_SLOT_ID . to_string ( ) ) ,
1368+ } ;
1369+ let visible_session_ids = ordered_visible_session_ids ( & view_state) ;
1370+ let terminals: Vec < TerminalInfo > = load_persisted_terminals_from_conn ( conn, workspace_id) ?
1371+ . into_iter ( )
1372+ . map ( |row| TerminalInfo {
1373+ id : row. terminal_id ,
1374+ output : row. output ,
1375+ recoverable : row. recoverable ,
1376+ } )
1377+ . collect ( ) ;
1378+ Ok ( SnapshotBase {
1379+ workspace,
1380+ view_state,
1381+ visible_session_ids,
1382+ terminals,
1383+ } )
1384+ }
1385+
1386+ fn apply_provider_sessions_to_snapshot_base (
1387+ mut base : SnapshotBase ,
1388+ provider_sessions : & [ ProviderWorkspaceSession ] ,
1389+ ) -> ( WorkspaceSnapshot , bool ) {
1390+ let mut sessions = Vec :: new ( ) ;
1391+ let mut binding_snapshots_changed = false ;
1392+
1393+ for session_id in & base. visible_session_ids {
1394+ let Some ( binding_index) = base
1395+ . view_state
1396+ . session_bindings
1397+ . iter ( )
1398+ . position ( |binding| binding. session_id == * session_id)
1399+ else {
1400+ continue ;
1401+ } ;
1402+ let binding = base. view_state . session_bindings [ binding_index] . clone ( ) ;
1403+ if let Some ( provider_session) = provider_session_for_binding ( provider_sessions, & binding) {
1404+ if base. view_state . session_bindings [ binding_index] . title_snapshot != provider_session. title
1405+ || base. view_state . session_bindings [ binding_index] . last_seen_at
1406+ != provider_session. last_active_at
1407+ {
1408+ base. view_state . session_bindings [ binding_index] . title_snapshot =
1409+ provider_session. title . clone ( ) ;
1410+ base. view_state . session_bindings [ binding_index] . last_seen_at =
1411+ provider_session. last_active_at ;
1412+ binding_snapshots_changed = true ;
1413+ }
1414+ }
1415+ sessions. push ( resolve_bound_session_from_binding (
1416+ & base. view_state . session_bindings [ binding_index] ,
1417+ provider_sessions,
1418+ ) ) ;
1419+ }
1420+
1421+ (
1422+ WorkspaceSnapshot {
1423+ workspace : base. workspace ,
1424+ sessions,
1425+ view_state : base. view_state ,
1426+ terminals : base. terminals ,
1427+ } ,
1428+ binding_snapshots_changed,
1429+ )
1430+ }
1431+
1432+ fn refresh_binding_snapshots_from_conn (
1433+ conn : & Connection ,
1434+ workspace_id : & str ,
1435+ updated_view_state : & WorkspaceViewState ,
1436+ ) -> Result < ( ) , String > {
1437+ let mut latest_view_state = match load_view_state_from_conn ( conn, workspace_id) {
1438+ Ok ( value) => value,
1439+ Err ( _) => default_view_state ( DEFAULT_SESSION_SLOT_ID . to_string ( ) ) ,
1440+ } ;
1441+ let mut changed = false ;
1442+
1443+ for updated_binding in & updated_view_state. session_bindings {
1444+ let Some ( latest_binding) = latest_view_state
1445+ . session_bindings
1446+ . iter_mut ( )
1447+ . find ( |binding| binding. session_id == updated_binding. session_id )
1448+ else {
1449+ continue ;
1450+ } ;
1451+ if latest_binding. title_snapshot != updated_binding. title_snapshot {
1452+ latest_binding. title_snapshot = updated_binding. title_snapshot . clone ( ) ;
1453+ changed = true ;
1454+ }
1455+ if latest_binding. last_seen_at != updated_binding. last_seen_at {
1456+ latest_binding. last_seen_at = updated_binding. last_seen_at ;
1457+ changed = true ;
1458+ }
1459+ }
1460+
1461+ if changed {
1462+ save_view_state_to_conn ( conn, workspace_id, & latest_view_state) ?;
1463+ }
1464+ Ok ( ( ) )
1465+ }
1466+
1467+ pub ( crate ) fn build_snapshot_outside_db_lock (
1468+ state : State < ' _ , AppState > ,
1469+ workspace_id : & str ,
1470+ ) -> Result < WorkspaceSnapshot , String > {
1471+ let base = with_db ( state, |conn| load_snapshot_base_from_conn ( conn, workspace_id) ) ?;
1472+ let provider_sessions = list_provider_workspace_sessions ( & base. workspace . project_path ) ?;
1473+ let ( snapshot, binding_snapshots_changed) =
1474+ apply_provider_sessions_to_snapshot_base ( base, & provider_sessions) ;
1475+ if binding_snapshots_changed {
1476+ with_db ( state, |conn| {
1477+ refresh_binding_snapshots_from_conn ( conn, workspace_id, & snapshot. view_state )
1478+ } ) ?;
1479+ }
1480+ Ok ( snapshot)
1481+ }
1482+
13531483pub ( crate ) fn build_snapshot_from_conn (
13541484 conn : & Connection ,
13551485 workspace_id : & str ,
@@ -1394,7 +1524,7 @@ pub(crate) fn build_snapshot_from_conn(
13941524 if binding_snapshots_changed {
13951525 save_view_state_to_conn ( conn, workspace_id, & view_state) ?;
13961526 }
1397- let terminals = load_persisted_terminals_from_conn ( conn, workspace_id) ?
1527+ let terminals: Vec < TerminalInfo > = load_persisted_terminals_from_conn ( conn, workspace_id) ?
13981528 . into_iter ( )
13991529 . map ( |row| TerminalInfo {
14001530 id : row. terminal_id ,
@@ -1606,17 +1736,17 @@ pub(crate) fn workspace_snapshot(
16061736 state : State < ' _ , AppState > ,
16071737 workspace_id : & str ,
16081738) -> Result < WorkspaceSnapshot , String > {
1609- with_db ( state, |conn| build_snapshot_from_conn ( conn , workspace_id) )
1739+ build_snapshot_outside_db_lock ( state, workspace_id)
16101740}
16111741
16121742pub ( crate ) fn load_workspace_slot_session (
16131743 state : State < ' _ , AppState > ,
16141744 workspace_id : & str ,
16151745 session_id : & str ,
16161746) -> Result < SessionInfo , String > {
1617- with_db ( state, |conn| {
1747+ let ( workspace , view_state , binding_index ) = with_db ( state, |conn| {
16181748 let workspace = load_workspace_row ( conn, workspace_id) ?;
1619- let mut view_state = load_view_state_from_conn ( conn, workspace_id) . or_else ( |_| {
1749+ let view_state = load_view_state_from_conn ( conn, workspace_id) . or_else ( |_| {
16201750 Ok :: < WorkspaceViewState , String > ( default_view_state (
16211751 DEFAULT_SESSION_SLOT_ID . to_string ( ) ,
16221752 ) )
@@ -1628,25 +1758,36 @@ pub(crate) fn load_workspace_slot_session(
16281758 else {
16291759 return Err ( "session_not_found" . to_string ( ) ) ;
16301760 } ;
1631- let provider_sessions = list_provider_workspace_sessions ( & workspace. root_path ) ?;
1632- let binding = view_state. session_bindings [ binding_index] . clone ( ) ;
1633- if let Some ( provider_session) = provider_session_for_binding ( & provider_sessions, & binding) {
1634- if view_state. session_bindings [ binding_index] . title_snapshot != provider_session. title
1635- || view_state. session_bindings [ binding_index] . last_seen_at
1636- != provider_session. last_active_at
1637- {
1638- view_state. session_bindings [ binding_index] . title_snapshot =
1639- provider_session. title . clone ( ) ;
1640- view_state. session_bindings [ binding_index] . last_seen_at =
1641- provider_session. last_active_at ;
1642- save_view_state_to_conn ( conn, workspace_id, & view_state) ?;
1643- }
1761+ Ok ( ( workspace, view_state, binding_index) )
1762+ } ) ?;
1763+
1764+ let provider_sessions = list_provider_workspace_sessions ( & workspace. root_path ) ?;
1765+ let binding = view_state. session_bindings [ binding_index] . clone ( ) ;
1766+ let mut updated_view_state = view_state. clone ( ) ;
1767+ let mut binding_snapshot_changed = false ;
1768+ if let Some ( provider_session) = provider_session_for_binding ( & provider_sessions, & binding) {
1769+ if updated_view_state. session_bindings [ binding_index] . title_snapshot != provider_session. title
1770+ || updated_view_state. session_bindings [ binding_index] . last_seen_at
1771+ != provider_session. last_active_at
1772+ {
1773+ updated_view_state. session_bindings [ binding_index] . title_snapshot =
1774+ provider_session. title . clone ( ) ;
1775+ updated_view_state. session_bindings [ binding_index] . last_seen_at =
1776+ provider_session. last_active_at ;
1777+ binding_snapshot_changed = true ;
16441778 }
1645- Ok ( resolve_bound_session_from_binding (
1646- & binding,
1647- & provider_sessions,
1648- ) )
1649- } )
1779+ }
1780+
1781+ if binding_snapshot_changed {
1782+ with_db ( state, |conn| {
1783+ refresh_binding_snapshots_from_conn ( conn, workspace_id, & updated_view_state)
1784+ } ) ?;
1785+ }
1786+
1787+ Ok ( resolve_bound_session_from_binding (
1788+ & updated_view_state. session_bindings [ binding_index] ,
1789+ & provider_sessions,
1790+ ) )
16501791}
16511792
16521793pub ( crate ) fn upsert_workspace_session_binding (
0 commit comments