Skip to content

Commit e06db84

Browse files
committed
fix: always reset isExecuting on query completion to prevent stuck tabs
1 parent 51a1775 commit e06db84

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

TablePro/Views/Main/Extensions/MainContentCoordinator+MultiStatement.swift

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,28 @@ extension MainContentCoordinator {
5252
try await driver.beginTransaction()
5353

5454
for (stmtIndex, sql) in statements.enumerated() {
55-
guard !Task.isCancelled else { break }
55+
guard !Task.isCancelled else {
56+
try? await driver.rollbackTransaction()
57+
await MainActor.run { [weak self] in
58+
guard let self else { return }
59+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
60+
tabManager.tabs[idx].isExecuting = false
61+
}
62+
currentQueryTask = nil
63+
toolbarState.setExecuting(false)
64+
}
65+
return
66+
}
5667
guard capturedGeneration == queryGeneration else {
5768
try? await driver.rollbackTransaction()
69+
await MainActor.run { [weak self] in
70+
guard let self else { return }
71+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
72+
tabManager.tabs[idx].isExecuting = false
73+
}
74+
currentQueryTask = nil
75+
toolbarState.setExecuting(false)
76+
}
5877
return
5978
}
6079

@@ -123,7 +142,19 @@ extension MainContentCoordinator {
123142
try? await driver.rollbackTransaction()
124143
}
125144

126-
guard capturedGeneration == queryGeneration else { return }
145+
// Always reset isExecuting even if generation is stale —
146+
// skipping this leaves the tab permanently stuck in "executing" state.
147+
if capturedGeneration != queryGeneration {
148+
await MainActor.run { [weak self] in
149+
guard let self else { return }
150+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
151+
tabManager.tabs[idx].isExecuting = false
152+
}
153+
currentQueryTask = nil
154+
toolbarState.setExecuting(false)
155+
}
156+
return
157+
}
127158

128159
let failedStmtIndex = executedCount + 1
129160
let contextMsg = "Statement \(failedStmtIndex)/\(totalCount) failed: "
@@ -189,7 +220,13 @@ extension MainContentCoordinator {
189220
toolbarState.setExecuting(false)
190221
toolbarState.lastQueryDuration = cumulativeTime
191222

192-
guard capturedGeneration == queryGeneration else { return }
223+
// Always reset isExecuting even if generation is stale
224+
if capturedGeneration != queryGeneration {
225+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
226+
tabManager.tabs[idx].isExecuting = false
227+
}
228+
return
229+
}
193230
guard let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) else {
194231
return
195232
}

TablePro/Views/Main/MainContentCoordinator.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ final class MainContentCoordinator {
911911
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
912912
tabManager.tabs[idx].isExecuting = false
913913
}
914+
currentQueryTask = nil
914915
toolbarState.setExecuting(false)
915916
toolbarState.lastQueryDuration = safeExecutionTime
916917
}
@@ -939,8 +940,13 @@ final class MainContentCoordinator {
939940
toolbarState.setExecuting(false)
940941
toolbarState.lastQueryDuration = safeExecutionTime
941942

942-
guard capturedGeneration == queryGeneration else { return }
943-
guard !Task.isCancelled else { return }
943+
// Always reset isExecuting even if generation is stale
944+
if capturedGeneration != queryGeneration || Task.isCancelled {
945+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
946+
tabManager.tabs[idx].isExecuting = false
947+
}
948+
return
949+
}
944950

945951
applyPhase1Result(
946952
tabId: tabId,
@@ -987,10 +993,17 @@ final class MainContentCoordinator {
987993
}
988994
}
989995
} catch {
990-
guard capturedGeneration == queryGeneration else { return }
991-
996+
// Always reset isExecuting even if generation is stale —
997+
// skipping this leaves the tab permanently stuck in "executing"
998+
// state, requiring a reconnect to recover.
992999
await MainActor.run { [weak self] in
9931000
guard let self else { return }
1001+
if let idx = tabManager.tabs.firstIndex(where: { $0.id == tabId }) {
1002+
tabManager.tabs[idx].isExecuting = false
1003+
}
1004+
currentQueryTask = nil
1005+
toolbarState.setExecuting(false)
1006+
guard capturedGeneration == queryGeneration else { return }
9941007
handleQueryExecutionError(error, sql: sql, tabId: tabId, connection: conn)
9951008
}
9961009
}

0 commit comments

Comments
 (0)