fix(coordinator): stop restored tabs from auto-running queries and spamming errors on launch (#1796)#1798
Conversation
…amming errors on launch (#1796)
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d2359bd22
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| guard let deferredId = deferredRestoreLoadTabId, | ||
| deferredId == tabManager.selectedTabId else { return } | ||
| deferredRestoreLoadTabId = nil | ||
| lazyLoadCurrentTabIfNeeded(trigger: .restore) |
There was a problem hiding this comment.
Restore schema before loading deferred tabs
When a restored background table tab becomes key after the connection is already established, this new deferred path goes straight to lazyLoadCurrentTabIfNeeded. Unlike the pending-load path in MainContentView+Helpers.consumePendingLoad, it never compares the tab's saved schemaName with session.currentSchema or calls restoreSchemaAndRunQuery, so a PostgreSQL tab restored from a non-current schema can run its first load and metadata/row-count fetches under the schema left active by another restored tab. Route deferred restore consumption through the same database/schema restoration step before loading.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8dac706d78
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for: restorePayload.id | ||
| ) | ||
| WindowManager.shared.openTab(payload: restorePayload) | ||
| WindowManager.shared.openTab(payload: restorePayload, activate: activate) |
There was a problem hiding this comment.
Don’t let background restores replace the command target
When restoring multiple tabs, this now opens every non-front tab with activate: false, but each restored window still runs configureWindow, which unconditionally assigns CommandActionsRegistry.shared.current even if window.isKeyWindow is false. In a multi-tab restore, whichever background tab finishes configuring last can become the fallback target for menu/keyboard commands, so actions like Run Query/New Tab may operate on a hidden restored tab until the user changes focus again; either avoid publishing for non-key background restores or republish the key window after opening them.
Useful? React with 👍 / 👎.
Fixes #1796.
Problem
Quitting TablePro with tabs open, then reopening, re-ran every restored table tab's data load. On PostgreSQL these failed and stacked a modal "Query Execution Failed" sheet per tab, with no way to stop them. The same connection worked fine in DBeaver.
Root cause (three compounding defects)
NSWindowRestorationand the app's ownAppLaunchCoordinatorreopen were both armed under the defaultReopen Last Session, arbitrated only by a 150ms timing guard. When restoration ran slower than 150ms, both fired and opened two window sets for the same connection. Each window then auto-ran the same query against the one shared connection; overlapping queries on a single PostgreSQL wire connection fail (works in DBeaver because it runs one query at a time).skipAutoExecuteflag meant to prevent this was dead on the restore path.Fix
windowDidBecomeKeyand the populate path, so it is immune to ordering.TableLoadTriggerthreaded end-to-end; a restore-triggered failure sets the inline error banner and skips the modal. User-initiated runs keep the dialog. ReplacedneedsLazyLoad: BoolwithpendingLoadTrigger: TableLoadTrigger?so the reason survives the wait-for-connection gap.This matches Apple's state-restoration guidance (restore UI state, load data on user intent) and how DataGrip and TablePlus behave.
Tests
RestoreWindowPlanTests(front-tab resolution, all branches) andTableLoadTriggerTests.MainContentCoordinatorLazyLoadTests(deferred no-op, become-key consume, restore-trigger carry) andMultiWindowRestorationTests(load-timing round-trip).Notes
--strictclean on changed files.NSWindowRestoration; the app's own reopen drives session restore.