Skip to content

feat: Oracle Cloud Wallet + connection resilience overhaul#107

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

feat: Oracle Cloud Wallet + connection resilience overhaul#107
Blankll merged 19 commits into
masterfrom
feat/oracle-connection-form

Conversation

@Blankll

@Blankll Blankll commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

Oracle ATP/ADW Cloud Wallet support, JDBC bridge hardening across all databases, and comprehensive connection resilience improvements.

Changes

Oracle Cloud Wallet (ATP/ADW)

  • Three connection methods: Basic (Host:Port), TNS (tnsnames.ora), Cloud Wallet
  • SID/Service Name toggle, Role selector (NORMAL/SYSDBA/SYSOPER)
  • JRE auto-install with download validation, atomic directory swap, 5-min timeout
  • Inline TNS descriptor from tnsnames.ora, JVM JKS keystore for mTLS
  • Password show/hide eye toggle on all fields
  • Step-by-step JDBC driver download with progress

JDBC Bridge Hardening

  • DriverManager bypass via setDataSource() fixes classloader isolation for all 22 JDBC databases
  • Full exception cause-chain traversal in error classification
  • Vendor error patterns for MySQL, PostgreSQL, SQL Server, Snowflake, DuckDB, H2
  • TDengine added to drivers.toml and registry
  • Stderr capture in connection errors

Connection Resilience

  • RwLock on connection pool map — parallel reads, no serialization bottleneck
  • Configurable connection timeout (default 10s) and query timeout (default 30s)
  • Timeout enforcement via tokio::time::timeout in connect and query commands
  • Connection Guardian: background health monitor with auto-reconnect (exponential backoff), idle eviction, and quality scoring
  • ConnectionHandle trait: unified interface eliminating 200+ lines of per-adapter match-arm dispatch in browse, query, and connection commands
  • LRU connection cache: bounded cache (max 20) with reconnect gate, wired into query flow and cleanup
  • Reactive frontend via Tauri events for connection state changes
  • Connection quality scoring (0-100) exposed via Tauri command + AI agent integration

Verification

  • 255/255 Rust tests pass
  • Java bridge builds clean
  • Zero compiler warnings
  • Oracle-verified: all 7 design goals met, 2 active bugs found and fixed

Blankll added 12 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.
@Blankll Blankll changed the title feat: enhance Oracle connection form with 3 connection methods and robust JRE download feat: Oracle Cloud Wallet + connection resilience (RwLock, timeouts, health monitor) Jun 20, 2026
Blankll added 6 commits June 20, 2026 16:05
…, 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.
@Blankll Blankll changed the title feat: Oracle Cloud Wallet + connection resilience (RwLock, timeouts, health monitor) feat: Oracle Cloud Wallet + connection resilience overhaul Jun 20, 2026
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.
@Blankll Blankll merged commit e3df9d9 into master Jun 20, 2026
3 checks passed
@Blankll Blankll deleted the feat/oracle-connection-form branch June 20, 2026 09:16
@Blankll Blankll restored the feat/oracle-connection-form branch June 20, 2026 09:30
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