Skip to content

feat: connection resilience — guardian, trait dispatch, LRU cache, JDBC driver expansion#109

Merged
Blankll merged 22 commits into
masterfrom
feat/oracle-connection-form
Jun 20, 2026
Merged

feat: connection resilience — guardian, trait dispatch, LRU cache, JDBC driver expansion#109
Blankll merged 22 commits into
masterfrom
feat/oracle-connection-form

Conversation

@Blankll

@Blankll Blankll commented Jun 20, 2026

Copy link
Copy Markdown
Member

Summary

Connection resilience follow-up: guardian health monitoring, unified adapter trait dispatch, LRU cache, JDBC driver expansion, and bug fixes.

Changes

Connection Guardian

  • Background health monitor checks all connections every 5s
  • Health state machine: Healthy → Degraded → Dead → Reconnecting
  • Auto-reconnect with exponential backoff (1s–30s)
  • Idle eviction after 30min of inactivity
  • Tauri events for reactive frontend state updates
  • Health check wired into execute_query and explain_query

ConnectionHandle Trait

  • Unified trait interface for all 9 adapter types
  • Eliminated 200+ lines of per-adapter match-arm dispatch
  • Wired into browse commands, connect/disconnect, and query execution

LRU Connection Cache

  • Bounded cache (max 20) with LRU eviction
  • Reconnect gate to prevent thundering herd
  • Populated on query execution, evicted on disconnect

JDBC Driver Download

  • Expanded download_jdbc_driver_direct from 3 hardcoded types to all 22 JDBC databases
  • Added DriverRegistry::get_config_by_name() for string-based lookup

Bug Fixes

  • connect_server now timeouts adapter.connect(), not just test_connection()
  • evict_idle boolean logic was inverted (connection leak)
  • MySQL list_schemas regression after trait migration
  • Removed unused imports after trait dispatch switch
  • Guardian accesses AppState via APP_HANDLE to avoid Tauri state type mismatch

Verification

  • 255/255 Rust tests pass
  • Zero compiler warnings
  • Clean build

Blankll added 22 commits June 20, 2026 01:46
…bust JRE download

- Add Oracle connection method selector (Basic/TNS/Cloud Wallet) with SID/Service Name toggle
- Add TNS names directory browser with auto-populated alias dropdown
- Add Cloud Wallet (ATP/ADW) support with wallet directory, password, and service level
- Add Role selector (NORMAL/SYSDBA/SYSOPER) with pill-toggle UI
- Redesign SSL/TLS mode as segmented radio group with hover descriptions
- Place Host/Port on same row, dynamic label for Service Name/SID field
- Add red asterisk indicators on required fields
- Increase dialog max-width from lg to xl

Backend:
- Add OracleConnectionOptions struct flowing through ServerConfig→ConnectionConfig→ConnectParams
- Implement build_oracle_url() with 4 URL formats (SID, Service Name, TNS, Cloud Wallet)
- Add tnsnames.ora parser for TNS alias auto-population
- Add direct JDBC driver download from Maven Central (no Java needed)
- Fix Adoptium JRE download URL (separate os/arch path segments)
- Add JRE download validation (size check, gzip magic bytes, atomic swap with rollback)
- Fix Java binary executable permission check (is_valid_java now checks +x)
- Handle macOS .jdk bundle format (Contents/Home/bin/java)
- Skip bridge JAR validation when Java is macOS stub
- Add process health check before bridge requests
- Skip non-JSON lines in bridge response parsing
- Retry empty bridge response after 1s delay

Java:
- Pass TNS_ADMIN and wallet_password as HikariCP data source properties
- Parse oracle_options from ConnectParams JSON

UI/UX:
- Add sequential step progress with per-item status and retry buttons
- Show download progress bar during JRE/bridge/driver downloads
- Add retry-on-error for individual setup steps
- Show loading indicator during connection test
- Add Connection successful/failed summary with error details
- Disable Test Connection and Save buttons during testing
- Prevent form submission on Browse buttons (type=button)
- Bundle carbon icons locally instead of CDN fetch
- Add error display for TNS/Wallet fields (tnsAdminDir, tnsAlias) with
  proper i18n keys instead of reusing hostRequired
- Add await to retryStep('driver') + concurrent-invocation guard in
  handleTestConnection to prevent race conditions
- Add onUnmounted cleanup for progress event listener to prevent leaks
- Preserve host/port when switching Oracle connection methods
- Use Content-Length header for download progress instead of hardcoded
  totals for accurate progress bars
Frontend (ServerFormDialog.vue):
- Validate SID/Service Name for Basic Oracle connections
- Password show/hide toggle on all 4 password fields
- Auto-clear corrupted TNS alias on edit when it doesn't match loaded aliases
- Remove misleading service level dropdown (alias suffix encodes it)
- Load TNS aliases when editing existing TNS/Wallet connections
- Preserve host/port across Oracle method switches
- New i18n keys: databaseRequired, tnsAdminDirRequired, tnsAliasRequired

Java bridge (ProtocolHandler.java, ConnectionManager.java):
- Full exception cause chain in error responses
- Bypass DriverManager for isolated-classloader drivers
- JVM SSL keyStore config (-Djavax.net.ssl.keyStore) for mTLS client cert

Rust (fallback.rs, launcher.rs, tns_parser.rs):
- Full TNS descriptor lookup from tnsnames.ora (inline URL format)
- JVM args plumbing for SSL keystore configuration
- Stderr capture in connection errors for diagnostics
G1 (P0): Add TDengine to drivers.toml and registry key mapping
G2 (P1): Add vendor-specific error patterns for MySQL, PostgreSQL,
        SQL Server, Snowflake, DuckDB, H2 in ErrorClassifier
G3 (P2): Refactor classify(String) -> classify(Throwable) with
        full exception cause-chain traversal
G4 (P3): Guard oracle_options to Oracle db_type only in
        to_connection_config() (defense-in-depth)
… trait, LRU cache

Commit 1: Foundation
- state.rs: Mutex<HashMap> -> RwLock<HashMap> for parallel reads
- config.rs: Add connect_timeout_secs (default 10s) + query_timeout_secs (default 30s)
  with builder methods and serde defaults
- state.rs: Propagate timeout fields in ServerConfig + to_connection_config()
- connection.rs: Enforce connect_timeout via tokio::time::timeout in connect_server
- query.rs: Enforce query_timeout via tokio::time::timeout in execute_query
- Lock migration: 38 .lock().await -> .read().await/.write().await across
  browse, connection, query, transfer, sql, commands (6 files)

Commit 2: Connection Guardian
- src/connection/guardian.rs: Single background tokio task monitoring all
  connections. Health state machine (Healthy->Degraded->Dead->Reconnecting).
  Auto-reconnect with exponential backoff (1s..30s). Idle eviction at 30min.
  Emits 'connection-state-changed' Tauri events for reactive frontend.

Commit 3: ConnectionHandle Trait
- src/connection/handle.rs: Object-safe trait unifying all 9 adapter types
- src/connection/handle_impl.rs: Implements trait on ActiveConnection via
  delegate! macro, eliminating 337+ match-arm dispatches across commands

Commit 4: LRU Connection Cache
- src/connection/cache.rs: Bounded LRU cache (max 20 entries) with pool-key
  based indexing. Reconnect gate (Notify) prevents thundering herd on
  simultaneous reconnects.

Frontend:
- connectionStore.ts: Add connectTimeoutSecs/queryTimeoutSecs to
  ServerConnection type. Serialize timeouts in test/connect server config.
  Add startStateListener() action listening for 'connection-state-changed'
  Tauri events for reactive connection status updates.

255/255 tests pass. Zero warnings.
tokio::spawn panics before the runtime is fully initialized in Tauri's
setup closure. Use tauri::async_runtime::spawn which is guaranteed to
have a reactor running.
Match dbx's pattern: flex-1 spacer with data-tauri-drag-region
between the title and action buttons provides a guaranteed
clear drag target for moving the window on macOS with
titleBarStyle: Overlay.
data-tauri-drag-region requires decorations:false to work.
dbx uses the same approach on Windows/Linux. Without this,
the native titlebar blocks the drag-region attribute on macOS.

This removes native traffic light buttons — the existing
pl-[90px] header padding reserves space to add custom
window controls later.
Revert set_decorations(false) on macOS — dbx keeps decorations:true
and relies on the native transparent titlebar for window dragging.

Remove data-tauri-drag-region from AppHeader to prevent
-webkit-app-region:drag from potentially conflicting with the
native titlebar drag behavior on macOS.
Bypass Tauri's data-tauri-drag-region handling with direct CSS
to ensure the header is recognized as a drag region. Tauri's
attribute translation may not be working reliably on all macOS
versions.
…ve elements

This is the standard Electron/frameless pattern: make the entire page
draggable by default and explicitly exclude buttons, inputs, links
and other interactive elements via -webkit-app-region:no-drag.

Eliminates dependency on per-element data-tauri-drag-region and
works reliably regardless of component nesting depth.
…, LRU cache

- Fix GUARDIAN.set() — the global was never initialized, making all
  health checks, quality scoring, and AI agent warnings silently skip.
  Now the guardian background task is properly stored and accessible.

- Wire ConnectionHandle trait into 3 commands:
  - connect_server: test_connection() replaces 9-variant match
  - disconnect_server: disconnect() replaces 9-variant match
  - execute_query: execute_query() + query_timeout_secs() replace
    147 lines of per-adapter variant matching
  Added query_timeout_secs() to the trait for timeout access.

- Wire LRU cache into AppState (cache field initialized, eviction
  on disconnect_server). Ready for cross-database query optimization.

The ConnectionHandle trait and LRU cache now deliver real value:
fewer match arms, cleaner commands, and infrastructure for future
adapter additions without touching every command file.
P0: Wrap create_and_connect_adapter() in connect_timeout.
Previously only test_connection() was guarded — a hung TCP/TLS
handshake in adapter.connect() would freeze the UI indefinitely.

P1: Fix inverted boolean in evict_idle. 'exists' was assigned
!contains_key(), then negated again in 'if !exists' — causing:
- Active connections to have their health records removed without
  actual disconnection (connection leak)
- Already-removed connections to trigger disconnect on nothing

Oracle audit: 7/7 goals verified, 2 active bugs fixed.
- Fix cache::get_or_create to accept &AppState instead of &Arc<AppState>
  so it's callable from Tauri commands via State<'_, AppState>
- Populate cache on every execute_query for cross-database reuse
- Add guardian health check to explain_query (was missing, only
  execute_query had it)
- Cache eviction already works on disconnect_server
After browsing command trait migration, MySQL list_schemas was
delegating to the adapter which returned ALL databases instead
of just the selected one. The old code had a MySQL special case:
'return Ok(vec![database]);'

Fix the MySQL adapter to use the database parameter: when a
specific database is given, return just that one. Otherwise
fall through to listing all databases.

Found by reviewer during browse command migration audit.
…e + explain_query

Deep agent finished migrating the remaining browse command handlers
and explain_query to use ConnectionHandle trait dispatch. Net reduction
of 49 lines across browse.rs, query.rs, and connectionStore.ts.
Previously only oracle, db2, h2 were supported — all other JDBC
databases returned 'No direct JDBC driver download'. Now uses
DriverRegistry::get_config_by_name() to look up any registered
JDBC driver configuration by its registry key.

Added get_config_by_name() to DriverRegistry for string-based
lookup, enabling the download command to accept any db_type from
the frontend without hardcoding a DatabaseType match.
ActiveConnection and DatabaseAdapter are no longer needed in
connection.rs after switching to ConnectionHandle dispatch.
Managing Arc<AppState> caused Tauri state() panic — Tauri's type
system couldn't match State<'_, AppState> against Arc<AppState>.
Guardian now accesses AppState through APP_HANDLE.state() with
proper let bindings for lifetime management.
@Blankll Blankll changed the title feat: connection resilience — RwLock, timeouts, health guardian, trait dispatch feat: connection resilience — guardian, trait dispatch, LRU cache, JDBC driver expansion Jun 20, 2026
@Blankll Blankll merged commit 652bf3d into master Jun 20, 2026
3 checks passed
@Blankll Blankll deleted the feat/oracle-connection-form branch June 20, 2026 09:46
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