diff --git a/connections/connection-form.mdx b/connections/connection-form.mdx index 7d46986..7d0a6d5 100644 --- a/connections/connection-form.mdx +++ b/connections/connection-form.mdx @@ -152,15 +152,16 @@ A connect you did not start never runs the script. A restored window at launch, Every active connection is checked on the interval set by **Check connections** in Settings > General, every 30 seconds by default, and the check is skipped while any query, export, import, or -other tracked operation is running. A failed check starts a reconnect at 2s, then 4s, 8s, doubling -to a 120-second ceiling, and keeps going until the connection comes back or you close it. An -authentication failure stops the retries and leaves the session in error. So does a TLS failure +other tracked operation is running. A failed check starts a +[reconnect](/connections#when-a-connection-drops): the rows stay on screen and the connection tries +10 times over about 10 minutes before it shows as lost. An authentication failure stops the +retries and shows the connection as lost at once. So does a TLS failure that needs an edit to the connection: TLS off where the server requires it, TLS on where the server refuses it, a client certificate the server requires, or a client key that cannot be read or decrypted. A server certificate that fails verification or does not match the host keeps the -retries going, and the window shows that certificate error in place of a generic one. A reconnect -rebuilds the tunnel, restores the selected database and schema, and re-runs the startup commands; -the session reads as connecting throughout. +retries going, and the reconnect bar names that certificate error as the cause in place of a +generic one. A reconnect rebuilds the tunnel, restores the selected database and schema, and +re-runs the startup commands; the connection shows as reconnecting throughout. The check is a query, so on a database that sleeps when idle or bills per query it is not free. **Only when I use the connection** stops it: TablePro sends nothing on its own, and instead checks the connection the first time you use it after five quiet minutes. Waking the Mac from sleep counts as a quiet period, so the first thing you do after opening the lid checks too. diff --git a/connections/index.mdx b/connections/index.mdx index 3e83897..f19d5e9 100644 --- a/connections/index.mdx +++ b/connections/index.mdx @@ -91,7 +91,7 @@ Press `Ctrl+Cmd+C` for **Switch Connection**. Whatever is already open sits at t Switching leaves the query tab you were in on its own connection. To take it with you, press `Ctrl+Option+Cmd+C` for **Move Tab to Connection…** instead. See [Moving a query tab to another connection](/features/tabs#moving-a-query-tab-to-another-connection). -A footer under that list names the transport the window's connection runs on. On an SSH tunnel or a SOCKS proxy it also carries the bytes that have crossed since the transport opened, received and sent, with the current rate beside each direction while something is moving. +A footer under that list names the transport the window's connection runs on. On an SSH tunnel or a SOCKS proxy it also carries the bytes that have crossed since the transport opened, received and sent, with the current rate beside each direction while something is moving. While the connection is connecting, reconnecting or lost, the footer shows that state in place of the byte counts. The rest show their name alone. Cloudflare Tunnel, Cloud SQL Auth Proxy and Tunnel Command each run a separate binary that holds the connection end to end, a [remote database file](/connections/remote-database-files) is fetched once and then read from disk, and a direct connection's socket belongs to the database driver. @@ -104,6 +104,18 @@ The rest show their name alone. Cloudflare Tunnel, Cloud SQL Auth Proxy and Tunn Leaving **Database** empty on MySQL, MariaDB, MongoDB, SQL Server, and ClickHouse browses every database the user can reach. PostgreSQL and Redshift need one to connect at all: use `postgres` (Redshift: `dev`) and switch with `Cmd+K`. System databases such as `mysql`, `information_schema` and `master` sit at the end of the switcher under **System**. To hide the rest, choose **View > Filter Databases** and select the ones you want; the choice is saved per connection and never hides a system database from the switcher. **View > Filter Schemas** does the same for the schemas of the database you are in. See [Filtering schemas](/features/connection-window#filtering-schemas). +## When a connection drops + +A tunnel or proxy that dies under a connection, or a server that stops answering the [health check](/connections/connection-form#connection-health), leaves the tabs and their rows on screen. A bar above them reads **Reconnecting to \ (1 of 10)** with the cause underneath, such as **SSH tunnel disconnected.**, and the count goes up with each try. + +The first try comes 2 seconds after the drop, then 4 and 8, doubling to 2 minutes between tries: 10 tries in about 10 minutes. **Cancel** on the bar stops the tries at once. When the tries run out, or you cancel, the pane reads **Disconnected from \** with the reason and a **Reconnect** button, and the tabs come back once it connects. + +Waking the Mac from sleep checks the tunnel of every open connection, and each one that died reconnects alongside the others rather than in turn. + +The connections strip, the welcome window and the connection switcher mark a reconnecting connection with a spinner and a lost one with a crossed-out bolt. [Connection state](/features/workspace-rail#connection-state) lists every mark. Hover one to read the cause. + +On the strip's right-click menu and in the **Database** menu, the connection command follows the state: **Connect**, **Reconnect**, **Stop Connecting** or **Stop Reconnecting**. The welcome window's right-click menu offers **Reconnect** for a lost connection and **Connect** for the rest. **Disconnect** stays on all three menus while a connection reconnects or is lost, and ends it without waiting for the next try. + ## Edit, delete, and where it all lives Right-click a connection to edit or delete it, or select it and press `Delete`. Deleting asks first and removes the saved settings, nothing on the server. Pressing `Delete` on a row under **Favorites** or **Recent** only takes it out of that section. Edits apply on the next connect. diff --git a/connections/socks-proxy.mdx b/connections/socks-proxy.mdx index 3ec6e61..80446f3 100644 --- a/connections/socks-proxy.mdx +++ b/connections/socks-proxy.mdx @@ -30,7 +30,7 @@ flowchart LR Driver -->|"loopback"| Relay -->|"SOCKS5"| SOCKS -->|"TCP"| Database ``` -No helper binary is involved: the relay is part of the app. It listens on a free loopback port and carries each connection through the proxy. If the relay dies mid-session, the connection reconnects and rebuilds it, up to ten attempts with a widening delay. +No helper binary is involved: the relay is part of the app. It listens on a free loopback port and carries each connection through the proxy. If the relay dies mid-session, the connection rebuilds it and [reconnects](/connections#when-a-connection-drops) with its rows still on screen. ## Setting up diff --git a/connections/ssh-tunneling.mdx b/connections/ssh-tunneling.mdx index 440a6fb..02b2a9e 100644 --- a/connections/ssh-tunneling.mdx +++ b/connections/ssh-tunneling.mdx @@ -131,7 +131,7 @@ A database on a socket cannot negotiate TLS, so SSL is switched off for the conn ## If the tunnel drops -A keep-alive goes out every 30 seconds. When one fails the session drops to connecting and the tunnel is rebuilt, retrying at 2s, 4s, 8s and doubling to a 120-second ceiling, ten attempts at most. A query in flight dies with the tunnel and is not replayed. After ten failures the session ends with **SSH tunnel disconnected. Click to reconnect.** +A keep-alive goes out every 30 seconds. When one fails, the rows stay on screen while the tunnel is rebuilt and the connection [reconnects](/connections#when-a-connection-drops), up to 10 tries. A query in flight dies with the tunnel and is not replayed. If every try fails, the pane reads **Disconnected from \**, gives the cause as **SSH tunnel disconnected.**, and offers **Reconnect**. If tunnels keep dropping on an idle network, the keep-alive is not the missing piece: check the server's `ClientAliveInterval` and the idle timeouts on any firewall or load balancer in between. diff --git a/connections/tunnel-command.mdx b/connections/tunnel-command.mdx index 7f9a8e2..ce7234b 100644 --- a/connections/tunnel-command.mdx +++ b/connections/tunnel-command.mdx @@ -69,7 +69,7 @@ Substitution happens after the split, so a value carrying a space stays a single ## While the connection is open -The process is held for the life of the connection and killed with its whole process group on disconnect, which is what takes an `aws ssm` session's helper down with it. If it exits on its own while the connection is still open, the connection reconnects and starts it again, up to ten attempts with a widening delay. That covers an SSM session hitting its idle timeout and a `kubectl port-forward` losing its pod. +The process is held for the life of the connection and killed with its whole process group on disconnect, which is what takes an `aws ssm` session's helper down with it. If it exits on its own while the connection is still open, the connection starts it again and [reconnects](/connections#when-a-connection-drops), with its rows still on screen. That covers an SSM session hitting its idle timeout and a `kubectl port-forward` losing its pod. The local port shares the connection's **Connect timeout** under **Options**, which uses 30 seconds when empty. Past that deadline the connect fails, and the error carries the last lines the command diff --git a/customization/appearance.mdx b/customization/appearance.mdx index 12cbb5c..5746e82 100644 --- a/customization/appearance.mdx +++ b/customization/appearance.mdx @@ -194,15 +194,13 @@ A file in the themes folder that breaks one of these is listed under **Not Loade Assign one with **Color** on the connection form's **Appearance** tab: None, Red, Orange, Yellow, Green, Blue, Purple, Pink, or Gray. With None, no color cue appears. Connection groups take a color the same way, from their right-click menu on the welcome window. -In the workspace rail the color is a dot on the corner of the database icon, and it stays visible on the selected row. In the welcome window list, the connection switcher and the query history drawer, it is a dot beside the name. The color's name is in the connection's tooltip and its VoiceOver label. - -The database icon keeps its engine's own color everywhere, whichever color the connection carries. +The connections strip, the welcome window list and the connection switcher draw the database icon on a rounded tile, and the color fills the tile, the selected row included. The engine's symbol on it turns white or black, whichever reads on that color. With None the tile is gray and the symbol keeps its engine's own color. In the query history drawer the color tints the network symbol beside the connection's name. On the strip, the color's name is in the entry's tooltip and its VoiceOver label. Use red for production databases as a visual reminder to be careful with queries. - - Connection colors on rail dots and welcome list rows - Connection colors on rail dots and welcome list rows + + Connection colors filling the icon tiles on the connections strip and in the welcome list + Connection colors filling the icon tiles on the connections strip and in the welcome list diff --git a/features/agent-mode.mdx b/features/agent-mode.mdx index 7093ab5..b63542e 100644 --- a/features/agent-mode.mdx +++ b/features/agent-mode.mdx @@ -85,11 +85,11 @@ Two views of one session, chosen from the menu at the trailing end of the column A run with no rows to draw says which of three things happened: **No Rows** for a query that matched nothing, **Statement Completed** for a write, with the number of rows it changed, and **Can't Show This Result** for a reply the grid cannot read, which the conversation still has in full. -`Cmd+Option+I` opens and closes this column, and the View menu's item reads **Show Result** while the mode is on. The column itself reads **No Session Open** until a session starts, and **Not Connected** while the connection is down. +`Cmd+Option+I` opens and closes this column, and the View menu's item reads **Show Result** while the mode is on. The column itself reads **No Session Open** until a session starts, **Connecting** while the connection opens, and **Not Connected** while it is down. ## When the connection drops -The conversation column is replaced by the same unavailable screen browsing shows: the error itself, **Manage Connections…**, and **Reconnect** for a connection that dropped or **Try Again** for one that failed. Reconnecting puts the same session and the same transcript back. +While the connection [reconnects](/connections#when-a-connection-drops), the conversation stays and the reconnect bar sits above it, with **Cancel**. Once the connection is lost or a connect fails, the column is replaced by the same unavailable screen browsing shows: the error itself, **Manage Connections…**, and **Reconnect** for a connection that dropped or **Try Again** for one that failed. Reconnecting puts the same session and the same transcript back. ## What Agent mode dims diff --git a/features/query-insights.mdx b/features/query-insights.mdx index f2de6d6..d912885 100644 --- a/features/query-insights.mdx +++ b/features/query-insights.mdx @@ -7,7 +7,7 @@ A query you ran 400 times with 400 different ids is one row here, not 400. That Needs a [Starter license](/features/licensing). -Open it with `Cmd+Option+Shift+I`, from **Database > Query Insights**, or by right-clicking a live connection in the [workspace rail](/features/workspace-rail). It opens as a tab, one per connection, and reuses the tab you already have open. +Open it with `Cmd+Option+Shift+I`, from **Database > Query Insights**, or by right-clicking a live connection in the [connections strip](/features/workspace-rail). It opens as a tab, one per connection, and reuses the tab you already have open. Query Insights tab diff --git a/features/server-dashboard.mdx b/features/server-dashboard.mdx index 789c479..c890f7c 100644 --- a/features/server-dashboard.mdx +++ b/features/server-dashboard.mdx @@ -13,7 +13,7 @@ What this screen shows is what your account is allowed to see. An empty or half- | MongoDB | Only your own operations; metrics and slow queries fail | `clusterMonitor`, `dbAdmin` on the database you browse for its profiler, and `hostManager` to cancel another user's operation | | Redis | A panel fails with `NOPERM` naming the command | `+client\|list`, `+client\|id`, `+info` and `+slowlog\|get` in the user's ACL, plus `+client\|kill` and `+client\|unblock` to act on a client | -Open it with `Cmd+Option+Shift+D`, from **Database > Server Dashboard**, from **Server Dashboard** under **Actions** in the toolbar, or by right-clicking a live connection in the [workspace rail](/features/workspace-rail). +Open it with `Cmd+Option+Shift+D`, from **Database > Server Dashboard**, from **Server Dashboard** under **Actions** in the toolbar, or by right-clicking a live connection in the [connections strip](/features/workspace-rail). Reconnect** | +| None | Connected, or not connected | Nothing | +| Spinner | Connecting, or [reconnecting](/connections#when-a-connection-drops) after a drop | Wait, or right-click and choose **Stop Connecting** or **Stop Reconnecting** | +| Crossed-out bolt, orange | The connection was lost, tabs kept | Click the entry, then **Reconnect** on the pane | +| Warning triangle, red | The last connect failed | Click the entry: the pane carries the driver's own error, **Try Again**, and **Copy Details** | + +The right-click menu leads with the command the state calls for; see [When a connection drops](/connections#when-a-connection-drops). ## When an entry appears @@ -48,7 +51,7 @@ Each entry keeps its own tabs. Clicking one shows its tabs and returns you to th Moving between schemas inside one database, such as PostgreSQL's, keeps the entry and its tabs. Tables of the same name in two schemas are told apart by their schema-qualified tab titles. -On PostgreSQL, Redshift, and CockroachDB every database entry keeps its own server connection, so moving between two entries reconnects nothing and leaves each database's open transaction and temp tables where they were. Closing an entry closes its connection and rolls back a transaction still open there, so it asks first when there is one. An hourglass on the entry's icon means a transaction is open there; on other engines it marks every entry of the connection, since one connection holds the transaction for all of them. +On PostgreSQL, Redshift, and CockroachDB every database entry keeps its own server connection, so moving between two entries reconnects nothing and leaves each database's open transaction and temp tables where they were. Closing an entry closes its connection and rolls back a transaction still open there, so it asks first when there is one. A badge on the corner of the entry's icon marks a transaction: an orange hourglass while one is open, a red warning triangle once a statement in it failed and only a rollback is left. On other engines the badge marks every entry of the connection, since one connection holds the transaction for all of them. The strip takes the keyboard too. Click into it, then use the arrow keys to move the highlight. Type the start of a connection, database, or schema name to jump to it, and press `Return` to open the entry. @@ -70,7 +73,7 @@ Right-click an entry and choose **Close Database “\”** to close that **Close Connection “\”**, below it, closes the whole connection: every tab across every database it has open, its session, and all of its entries. The window closes too if that was its last connection, and **File > Close Connection** does the same for the connection on screen. A connection down to one entry has nothing else left, so closing that entry closes it. Nothing is lost for good: reopen the connection, from the connection list or **Database > Switch Connection…**, and its tabs come back as they were. -**Disconnect**, on the same menu while the connection is live, ends the session and keeps everything else. No window closes, no entry disappears, and the tabs are saved first; the connection shows a Reconnect pane in their place until **Database > Reconnect**, or the pane's own button, brings both back. **Database > Disconnect** does the same for the connection on screen, asking first when a transaction is open, a query is running, or changes are unsaved. Nothing reconnects on its own, a relaunch included: a connection you disconnected comes back on the strip as **Not connected**. +**Disconnect**, on the same menu while the connection is up, reconnecting or lost, ends the session and keeps everything else. No window closes, no entry disappears, and the tabs are saved first; the pane reads **Disconnected from \** in their place until its **Reconnect** button, or **Connect** on the right-click menu or the **Database** menu, brings both back. **Database > Disconnect** does the same for the connection on screen, asking first when a transaction is open, a query is running, or changes are unsaved. Nothing reconnects on its own, a relaunch included: a connection you disconnected comes back on the strip as **Not connected**. ## Reordering diff --git a/images/workspace-rail-dark.png b/images/workspace-rail-dark.png index f49d715..7684425 100644 Binary files a/images/workspace-rail-dark.png and b/images/workspace-rail-dark.png differ diff --git a/images/workspace-rail.png b/images/workspace-rail.png index 0ff5b43..cfffd22 100644 Binary files a/images/workspace-rail.png and b/images/workspace-rail.png differ diff --git a/ios/index.mdx b/ios/index.mdx index 20085ff..cc8a400 100644 --- a/ios/index.mdx +++ b/ios/index.mdx @@ -263,6 +263,14 @@ The bar shows on PostgreSQL, Redshift, MySQL, MariaDB, TiDB, SQLite, Oracle, Duc A connection that drops with a transaction open reconnects and says the server rolled the transaction back. One that drops during **Commit** never got the answer: check which changes were saved before running them again. Switching database on PostgreSQL or Redshift, saving a connection edit that reconnects, or deleting the connection asks first while a transaction is open, since each rolls it back. On MySQL, MariaDB, TiDB, OceanBase and Oracle, **Truncate** and **Drop** commit an open transaction, and their confirmation says so. Two iPad windows on one connection follow each other's database switch. +### When the connection drops + +Returning to the app, reopening a connection that is still open, or a tunnel that dies checks the session, and one that stopped answering is dialed again once. While that runs, **Reconnecting** and a spinner sit in the toolbar and the screen stays as it was. A database or schema switch shows **Switching to \…** in the same place; the content takes no taps until it lands, and the tabs and **Connections** stay usable. + +When the redial fails, **Connection lost** takes the screen with the error and **Reconnect**. A row with unsaved edits keeps its screen instead, and **Reconnect** sits in the toolbar. A connect that fails shows its error the same way, with **Edit Connection** beside **Reconnect** when the fix is in the form. + +The **Status** row in **Info** uses the same words: **Connected**, **Not Connected**, **Connecting**, **Reconnecting**, **Connection lost** or **Couldn't connect**. + ## What is missing - **Schema changes.** Truncating and dropping a table is the whole list; creating or altering tables, columns, indexes, triggers, and views is Mac only, and so is creating or dropping a Cloudflare D1 database. @@ -277,7 +285,7 @@ Turn on Face ID, Touch ID, or Optic ID under **Settings > Security**. A cold lau Each connection carries its own [safe mode](/features/safe-mode) level, synced from the Mac. Set it with **Safe Mode** under **Organization** in the connection's form. iOS has three: **Off**, **Confirm Writes**, and **Read-Only**, which refuses writes outright. **Default Safe Mode** under **Settings > New Connections** sets the level a new connection starts at. -SSH tunnels authenticate with a password, a private key or **Keyboard Interactive**. A tunnel set to **SSH Agent** on the Mac signs in here with a private key on this device and stays **SSH Agent** on the Mac. When the server asks for more, after the password or key or through keyboard-interactive, a password prompt gets the SSH password and a code prompt gets the code from **Two-Factor Authentication**. Any other question, or a code in **Prompt at Connect** mode, appears on the connection's screen for you to answer. **Auto Generate** takes the Base32 secret from your authenticator setup with its algorithm, digits and period, and shares them with the Mac; a tunnel that follows a Mac SSH profile uses the profile's. A private key on a security key does not work here, and the **SSH Sign-In Unavailable** alert says so. An unknown host key, the SSH server's or a jump host's, prompts with its fingerprint first, on the connection's own screen. The question waits there until you answer it, and leaving the screen ends that attempt. A key pasted under **Paste Key**, or picked as a text file, is kept in the Keychain beside the connection's passwords, never in the saved connection list. A key file that is not text is copied into the app and read from there. Setting **Auth Method** to **Password**, choosing **Import File**, or turning **SSH Tunnel** off deletes the saved key when you tap **Save**. A tunnel the Mac forwards to a unix socket on the server forwards to the same socket here. Turning the tunnel off keeps its other settings, here and on the Mac, for when you turn it back on. A tunnel that drops while the connection is open reconnects it, as returning to the app does. +SSH tunnels authenticate with a password, a private key or **Keyboard Interactive**. A tunnel set to **SSH Agent** on the Mac signs in here with a private key on this device and stays **SSH Agent** on the Mac. When the server asks for more, after the password or key or through keyboard-interactive, a password prompt gets the SSH password and a code prompt gets the code from **Two-Factor Authentication**. Any other question, or a code in **Prompt at Connect** mode, appears on the connection's screen for you to answer. **Auto Generate** takes the Base32 secret from your authenticator setup with its algorithm, digits and period, and shares them with the Mac; a tunnel that follows a Mac SSH profile uses the profile's. A private key on a security key does not work here, and the **SSH Sign-In Unavailable** alert says so. An unknown host key, the SSH server's or a jump host's, prompts with its fingerprint first, on the connection's own screen. The question waits there until you answer it, and leaving the screen ends that attempt. A key pasted under **Paste Key**, or picked as a text file, is kept in the Keychain beside the connection's passwords, never in the saved connection list. A key file that is not text is copied into the app and read from there. Setting **Auth Method** to **Password**, choosing **Import File**, or turning **SSH Tunnel** off deletes the saved key when you tap **Save**. A tunnel the Mac forwards to a unix socket on the server forwards to the same socket here. Turning the tunnel off keeps its other settings, here and on the Mac, for when you turn it back on. A tunnel that drops while the connection is open reconnects it, as returning to the app does; see [When the connection drops](#when-the-connection-drops). ### Jump hosts diff --git a/troubleshooting.mdx b/troubleshooting.mdx index 9d8f56a..59cf93b 100644 --- a/troubleshooting.mdx +++ b/troubleshooting.mdx @@ -27,10 +27,11 @@ A failure that happens on one engine only is on that engine's page, which ends w ## A connection fails -A failed connect paints the window with **Could not connect to `…`**, the driver's own message, and three buttons: **Try Again**, **Manage Connections…**, **Copy Details**. +A failed connect paints the connection's window with **Could not connect to `…`**, the driver's own message, and three buttons: **Try Again**, **Manage Connections…**, **Copy Details**. That holds for a connect started from the welcome window or the connection switcher too: the error lands in the window, not in an alert. - **Refused** means something answered and said no: the server is not listening on that port, or it is bound to `127.0.0.1` only. **Timed out** means nothing answered, which points at a firewall, a security group or a VPN. Tell them apart with `nc -zv host port`. - **Still on Connecting**: after 12 seconds on one step the pane says "This is taking longer than usual." **Cancel** gives up at once. **Reopen Last Session** brings that connection back as **Not connected** without dialing it; a connect that fails on its own dials again. +- **Disconnected from `…`** after a run of **Reconnecting to `…`**: the tunnel, the proxy or the server dropped, and every try failed or you clicked **Cancel**. The pane names the cause; fix it and click **Reconnect**. See [When a connection drops](/connections#when-a-connection-drops). - On macOS 15 and later, a host at a local network address (`192.168.x.x`, `10.x.x.x`, `.local`) needs the Local Network permission. Without it the window reads **Local Network Access Required** and names the host it could not reach: the database, the SSH server or jump host, or the SOCKS proxy. **Open System Settings** takes you to **Privacy & Security**; turn TablePro on under **Local Network**, then click **Try Again**. **Copy Details** still holds the driver's message. Loopback and internet hosts are unaffected. - Authentication failures are engine-specific. See [PostgreSQL](/databases/postgresql), [MySQL](/databases/mysql) or [SQL Server](/databases/mssql).