Skip to content

feat(plugin-redis): add Sentinel connection mode (#1021)#1215

Open
tonghs wants to merge 3 commits intoTableProApp:mainfrom
tonghs:feat/plugin-redis-sentinel-1021
Open

feat(plugin-redis): add Sentinel connection mode (#1021)#1215
tonghs wants to merge 3 commits intoTableProApp:mainfrom
tonghs:feat/plugin-redis-sentinel-1021

Conversation

@tonghs
Copy link
Copy Markdown
Contributor

@tonghs tonghs commented May 11, 2026

Summary

Phase 1 of #1021: adds Redis Sentinel connection mode to the Redis plugin. Users with Sentinel-fronted HA deployments can now point TablePro at the Sentinel quorum instead of a single underlying Redis node, and reconnects automatically follow master failover.

Cluster mode (Phase 2 of the issue) is not in this PR.

Closes Phase 1 of #1021.

image

What this PR does

Sentinel resolution path (Plugins/RedisDriverPlugin/)

  • New RedisSentinelResolver — pure Swift, iterates Sentinel nodes in order, returns first node's master address; throws .masterUnknown (vs .allSentinelsUnreachable) when at least one Sentinel responded but didn't know the master
  • New HiredisSentinelTransport — production transport, opens a short-lived hiredis connection per Sentinel, runs SENTINEL get-master-addr-by-name, applies optional Sentinel-plane AUTH separately from data-plane AUTH
  • RedisPluginDriver.connect() now branches on a new `redisMode` field; sentinel mode runs the resolver, then opens the existing single-node connection to the resolved master. The resolver re-runs on every reconnect (no cached address), so ConnectionHealthMonitor failover Just Works

Connection form schema (RedisPlugin.swift + PluginMetadataRegistry+RegistryDefaults.swift)

  • New fields: Connection Mode (Single Node / Sentinel), Sentinel Nodes (hostList), Master Group Name (defaults `mymaster`), Sentinel User, Sentinel Password
  • All Sentinel-related fields live in the Connection section and use visibleWhen to hide in Single mode

Two framework fixes uncovered while wiring this up (split into separate commits)

  • fix(plugins): PluginMetadataSnapshot.withBranding was overwriting the plugin's connection with the registry default's. When a plugin added new additionalConnectionFields to its source without also updating RegistryDefaults, the new fields were silently dropped. Only preserves visual branding now (displayName / iconName / brandColorHex)
  • fix(connection-form): hasHostListField is now visibility-aware (was returning true whenever any hostList field existed in metadata, even when hidden); AuthPaneViewModel.isFieldVisible now falls back to the network pane's field values so cross-section visibleWhen rules work; HostListFieldRow placeholder used Text("hostname:\(defaultPort)") which let SwiftUI render the Int as a localized number with thousand separators (hostname:6,379) — switched to Text(verbatim:). Also affects MongoDB

Test plan

  • RedisSentinelResolverTests — 22 cases covering iteration semantics, reply parsing, hostList parsing
  • PluginMetadataRegistryBrandingTests — 2 cases locking in the withBranding fix
  • Local integration test against Docker Sentinel topology (1 master + 2 replica + 3 sentinel); recommended manual setup is documented in the spec but not in CI
  • Full TablePro test suite was run on my branch; the failures listed in my local report are all pre-existing on `main` (ClickHouse SQL gen, MCP, SafeMode, SSH, Cassandra icon, etc.) and unrelated to this change

Notes for the maintainer

UI is not my strong suit. I tried to follow existing connection-form conventions (visibleWhen, hostList, dropdown), and reordered Sentinel fields a few times based on RedisInsight as reference. If you'd rather restructure the form (e.g., segmented control for Mode, distinct "Sentinel" subsection, different field naming), feel free to take over that part. I'd rather you redo the UI than ship something off-brand.

Localization: I only verified English and Chinese (zh-Hans). I added Turkish and Vietnamese translations on a best-effort basis (no native review), so please have them sanity-checked by speakers if you have access. The 12 new strings live in TablePro/Resources/Localizable.xcstrings.

No native protocol changes: the plugin's additionalConnectionFields array is the source of truth, but RegistryDefaults.swift mirrors it (because built-in plugins are lazily instantiated, so the form reads the registry default before the plugin loads). That's an existing convention in this codebase; if you'd like, a follow-up could collapse the dual source by lazy-activating the driver on first metadata read.

Open question in the issue I didn't pick up: Q3 (hiredis vs hiredis-cluster) is irrelevant for Sentinel; it'll come back when Phase 2 (Cluster) starts.

@tonghs tonghs marked this pull request as ready for review May 11, 2026 09:05
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