fix(tmux): preserve isolated container cleanup after anchor reassignment
This commit is contained in:
@@ -1091,6 +1091,7 @@ describe('TmuxSessionManager', () => {
|
|||||||
paneId: '%isolated-session-ses_first',
|
paneId: '%isolated-session-ses_first',
|
||||||
sessionId: 'ses_first',
|
sessionId: 'ses_first',
|
||||||
})
|
})
|
||||||
|
expect(Reflect.get(manager, 'isolatedContainerPaneId')).toBeUndefined()
|
||||||
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBeUndefined()
|
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1177,18 +1178,25 @@ describe('TmuxSessionManager', () => {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
expect(mockExecuteAction).toHaveBeenCalledTimes(0)
|
expect(mockExecuteAction).toHaveBeenCalledTimes(0)
|
||||||
|
expect(Reflect.get(manager, 'isolatedContainerPaneId')).toBe('%isolated-session-ses_first')
|
||||||
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBe('%mock')
|
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBe('%mock')
|
||||||
|
|
||||||
// when
|
// when
|
||||||
await manager.onSessionDeleted({ sessionID: 'ses_second' })
|
await manager.onSessionDeleted({ sessionID: 'ses_second' })
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(mockExecuteAction).toHaveBeenCalledTimes(1)
|
expect(mockExecuteAction).toHaveBeenCalledTimes(2)
|
||||||
expect(mockExecuteAction.mock.calls[0]?.[0]).toEqual({
|
expect(mockExecuteAction.mock.calls[0]?.[0]).toEqual({
|
||||||
type: 'close',
|
type: 'close',
|
||||||
paneId: '%mock',
|
paneId: '%mock',
|
||||||
sessionId: 'ses_second',
|
sessionId: 'ses_second',
|
||||||
})
|
})
|
||||||
|
expect(mockExecuteAction.mock.calls[1]?.[0]).toEqual({
|
||||||
|
type: 'close',
|
||||||
|
paneId: '%isolated-session-ses_first',
|
||||||
|
sessionId: 'ses_second',
|
||||||
|
})
|
||||||
|
expect(Reflect.get(manager, 'isolatedContainerPaneId')).toBeUndefined()
|
||||||
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBeUndefined()
|
expect(Reflect.get(manager, 'isolatedWindowPaneId')).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export class TmuxSessionManager {
|
|||||||
private nullStateCount = 0
|
private nullStateCount = 0
|
||||||
private deps: TmuxUtilDeps
|
private deps: TmuxUtilDeps
|
||||||
private pollingManager: TmuxPollingManager
|
private pollingManager: TmuxPollingManager
|
||||||
|
private isolatedContainerPaneId: string | undefined
|
||||||
private isolatedWindowPaneId: string | undefined
|
private isolatedWindowPaneId: string | undefined
|
||||||
constructor(ctx: PluginInput, tmuxConfig: TmuxConfig, deps: TmuxUtilDeps = defaultTmuxDeps) {
|
constructor(ctx: PluginInput, tmuxConfig: TmuxConfig, deps: TmuxUtilDeps = defaultTmuxDeps) {
|
||||||
this.client = ctx.client
|
this.client = ctx.client
|
||||||
@@ -125,6 +126,7 @@ export class TmuxSessionManager {
|
|||||||
if (this.isolatedWindowPaneId) {
|
if (this.isolatedWindowPaneId) {
|
||||||
const state = await queryWindowState(this.isolatedWindowPaneId).catch(() => null)
|
const state = await queryWindowState(this.isolatedWindowPaneId).catch(() => null)
|
||||||
if (state) return null
|
if (state) return null
|
||||||
|
this.isolatedContainerPaneId = undefined
|
||||||
this.isolatedWindowPaneId = undefined
|
this.isolatedWindowPaneId = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +138,7 @@ export class TmuxSessionManager {
|
|||||||
: await spawnTmuxWindow(sessionId, title, this.tmuxConfig, this.serverUrl)
|
: await spawnTmuxWindow(sessionId, title, this.tmuxConfig, this.serverUrl)
|
||||||
|
|
||||||
if (result.success && result.paneId) {
|
if (result.success && result.paneId) {
|
||||||
|
this.isolatedContainerPaneId = result.paneId
|
||||||
this.isolatedWindowPaneId = result.paneId
|
this.isolatedWindowPaneId = result.paneId
|
||||||
log("[tmux-session-manager] isolated container created", {
|
log("[tmux-session-manager] isolated container created", {
|
||||||
isolation,
|
isolation,
|
||||||
@@ -172,10 +175,10 @@ export class TmuxSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private reassignIsolatedContainerAnchor(): boolean {
|
private reassignIsolatedContainerAnchor(): void {
|
||||||
const nextAnchor = this.sessions.values().next().value
|
const nextAnchor = this.sessions.values().next().value
|
||||||
if (!nextAnchor) {
|
if (!nextAnchor) {
|
||||||
return false
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isolatedWindowPaneId = nextAnchor.paneId
|
this.isolatedWindowPaneId = nextAnchor.paneId
|
||||||
@@ -183,7 +186,6 @@ export class TmuxSessionManager {
|
|||||||
sessionId: nextAnchor.sessionId,
|
sessionId: nextAnchor.sessionId,
|
||||||
paneId: nextAnchor.paneId,
|
paneId: nextAnchor.paneId,
|
||||||
})
|
})
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async cleanupIsolatedContainerAfterSessionDeletion(
|
private async cleanupIsolatedContainerAfterSessionDeletion(
|
||||||
@@ -196,22 +198,25 @@ export class TmuxSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.sessions.size > 0) {
|
if (this.sessions.size > 0) {
|
||||||
if (this.reassignIsolatedContainerAnchor()) {
|
this.reassignIsolatedContainerAnchor()
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isolatedContainerPaneId = this.isolatedContainerPaneId
|
||||||
|
this.isolatedContainerPaneId = undefined
|
||||||
this.isolatedWindowPaneId = undefined
|
this.isolatedWindowPaneId = undefined
|
||||||
|
|
||||||
if (isolatedPaneAlreadyClosed) {
|
if (!isolatedContainerPaneId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isolatedPaneAlreadyClosed && tracked.paneId === isolatedContainerPaneId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await executeAction(
|
const result = await executeAction(
|
||||||
{ type: "close", paneId: tracked.paneId, sessionId: tracked.sessionId },
|
{ type: "close", paneId: isolatedContainerPaneId, sessionId: tracked.sessionId },
|
||||||
{
|
{
|
||||||
config: this.tmuxConfig,
|
config: this.tmuxConfig,
|
||||||
serverUrl: this.serverUrl,
|
serverUrl: this.serverUrl,
|
||||||
@@ -223,13 +228,13 @@ export class TmuxSessionManager {
|
|||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
log("[tmux-session-manager] failed to close isolated container pane after anchor session deletion", {
|
log("[tmux-session-manager] failed to close isolated container pane after anchor session deletion", {
|
||||||
sessionId: tracked.sessionId,
|
sessionId: tracked.sessionId,
|
||||||
paneId: tracked.paneId,
|
paneId: isolatedContainerPaneId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log("[tmux-session-manager] failed to cleanup isolated container pane after anchor session deletion", {
|
log("[tmux-session-manager] failed to cleanup isolated container pane after anchor session deletion", {
|
||||||
sessionId: tracked.sessionId,
|
sessionId: tracked.sessionId,
|
||||||
paneId: tracked.paneId,
|
paneId: isolatedContainerPaneId,
|
||||||
error: String(error),
|
error: String(error),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -855,6 +860,7 @@ export class TmuxSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await this.retryPendingCloses()
|
await this.retryPendingCloses()
|
||||||
|
this.isolatedContainerPaneId = undefined
|
||||||
this.isolatedWindowPaneId = undefined
|
this.isolatedWindowPaneId = undefined
|
||||||
|
|
||||||
log("[tmux-session-manager] cleanup complete")
|
log("[tmux-session-manager] cleanup complete")
|
||||||
|
|||||||
Reference in New Issue
Block a user