Skip to content

fix(ssh): Add SSH keep-alive to MySQL client (#32494)#41879

Open
mbijon wants to merge 2 commits into
appsmithorg:releasefrom
mbijon:fix/32494-mysql-ssh-keepalive
Open

fix(ssh): Add SSH keep-alive to MySQL client (#32494)#41879
mbijon wants to merge 2 commits into
appsmithorg:releasefrom
mbijon:fix/32494-mysql-ssh-keepalive

Conversation

@mbijon

@mbijon mbijon commented Jun 6, 2026

Copy link
Copy Markdown

Description

This fix implements a standard SSH keep-alive to keep the MySQL SSH client tunnel warm. An idle SSH tunnel (e.g. no queries for hours) gets silently dropped by NATs, firewalls, or the SSH server. Because sshj doesn't notice the drop, isSSHTunnelConnected() keeps reporting the tunnel as connected, so Appsmith reuses a dead tunnel and queries fail until the tunnel is reset or recreated.

Stale tunnels are still correctly detected and recreated. Enough unanswered probes cause sshj to tear the transport down, isConnected() flips to false, and the connection is classified as stale.

Fixes #32494
https://github.com/appsmithorg/appsmith/issues/32494
@vivek-appsmith

JUnit Coverage improvements

│ Class │ Lines │ Branches │ Methods │
│ MySqlDatasourceUtils │ 44% → 98% (113/115) │ 51% → 76% │ 3/6 → 6/6 │
│ MySqlPlugin$MySqlPluginExecutor │ 15% → 51% (183/359) │ 9% → 35% │ 12/54 → 31/54│

Now covered (was 0%)

MySqlDatasourceUtilsTest (10 tests) — the connection-building logic:

  • getBuilder: standard host:port URL, SSH→localhost-forwarded-port, serverTimezone property, and the no-endpoints URL fallback
  • addSslOptionsToBuilder: REQUIRED / DISABLED / DEFAULT / unsupported-type-throws / missing-config-throws
  • getNewConnectionPool

MySqlPluginExecutorUnitTest (12 tests) — pure helpers + lifecycle:

  • getEndpointIdentifierForRateLimit (standard + SSH), isIsOperatorUsed, getSchemaPreviewActionConfig
  • testDatasource (success + failure), datasourceCreate, datasourceDestroy (verifies tunnel socket/client/thread + pool teardown)
  • executeParameterized (missing-query, prepared + non-prepared paths)
  • getStructure with a dead SSH tunnel → StaleConnectionException — mirrors the executeCommon stale gate, so the fix's liveness check is now covered in both query and schema-fetch paths

Automation

/ok-to-test tags=""

🔍 Cypress test results

Caution

If you modify the content in this section, you are likely to disrupt the CI result for your PR.

Communication

Should the DevRel and Marketing teams inform users about this change?

  • I don't know

Summary by CodeRabbit

  • New Features

    • SSH tunnels now support keep-alive functionality to detect and prevent stale connections.
    • Enhanced error detection when SSH tunnel connections become disconnected during MySQL queries.
  • Tests

    • Added comprehensive test coverage for MySQL plugin executor, datasource utilities, and SSH tunnel stale-connection scenarios.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine.

Review Change Stack

Walkthrough

This PR adds SSH keep-alive configuration to prevent stale tunnel detection and introduces three new comprehensive test suites for MySQL datasource operations. SSHUtils now configures keep-alive probes with a public interval constant. The test coverage spans executor operations, connection utilities, SSL handling, and SSH tunnel failure scenarios.

Changes

SSH Keep-Alive Infrastructure and MySQL Plugin Comprehensive Test Suite

Layer / File(s) Summary
SSH Keep-Alive Infrastructure
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/SSHUtils.java, app/server/appsmith-interfaces/src/test/java/com/appsmith/external/helpers/SSHUtilsTest.java
SSHUtils adds SSH_KEEP_ALIVE_INTERVAL_SECONDS constant and configures SSHJ clients with DefaultConfig and KeepAliveProvider. After authentication, the keep-alive interval is set on the connection. Tests verify the constant is positive and under 300 seconds.
MySqlPluginExecutor Comprehensive Unit Tests
app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/plugins/MySqlPluginExecutorUnitTest.java
New mock-based test class covering endpoint identifiers for rate limiting, SQL IS operator detection, schema preview action config, datasource lifecycle (testing, pool creation, cleanup), parametrized query execution error handling, and stale connection detection when SSH tunnels disconnect.
SSH Tunnel Staleness Error Detection Tests
app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/plugins/MySqlStaleConnectionErrorMessageTest.java
Extends error message tests with two new scenarios: SSH client disconnected and SSH authentication lost. Both verify StaleConnectionException with CONNECTION_VALIDITY_CHECK_FAILED_ERROR_MSG when local DB validation passes but the tunnel is dead.
MySqlDatasourceUtils Connection and SSL Tests
app/server/appsmith-plugins/mysqlPlugin/src/test/java/com/external/utils/MySqlDatasourceUtilsTest.java
New test suite validating connection builder configuration: endpoint-based and URL-based host/port resolution, SSH tunnel forwarding to localhost and forwarded ports, serverTimezone propagation, and SSL option handling for REQUIRED/DISABLED/DEFAULT auth types. Negative tests verify exceptions for unsupported auth types and missing SSL config.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🔌 SSH tunnels now keep their heartbeat alive,
with probes that prevent the stale-connection dive,
While three new test suites stand guard day and night,
ensuring connection, configuration, and pooling are right. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is comprehensive and covers motivation, technical details, coverage improvements with metrics, and addresses the issue fix. However, the Communication checkbox shows 'I don't know' rather than a definitive Yes/No selection.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: adding SSH keep-alive functionality to the MySQL client tunnel to prevent idle connections from being silently dropped.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mbijon mbijon changed the title Add SSH keep-alive to MySQL client (#32494) fix(ssh): Add SSH keep-alive to MySQL client (#32494) Jun 9, 2026
@github-actions

Copy link
Copy Markdown

This PR has not seen activitiy for a while. It will be closed in 7 days unless further activity is detected.

@github-actions github-actions Bot added the Stale label Jun 16, 2026
@mbijon

mbijon commented Jun 16, 2026

Copy link
Copy Markdown
Author

@sumitsum this should fix your bug report #32494. Can you test it & comment here?

@github-actions github-actions Bot removed the Stale label Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant