Skip to content

Add redis-proxy: dual-write Redis proxy with pub/sub forwarding#351

Merged
bootjp merged 97 commits intomainfrom
feature/redis-proxy
Mar 20, 2026
Merged

Add redis-proxy: dual-write Redis proxy with pub/sub forwarding#351
bootjp merged 97 commits intomainfrom
feature/redis-proxy

Conversation

@bootjp
Copy link
Copy Markdown
Owner

@bootjp bootjp commented Mar 17, 2026

Implement a Redis-protocol proxy that supports dual-write to primary (Redis) and secondary (ElasticKV) backends. Includes full pub/sub message forwarding via redcon Detach + go-redis PubSub.

Verified all 581 Misskey unit tests pass through the proxy.

Implement a Redis-protocol proxy that supports dual-write to primary
(Redis) and secondary (ElasticKV) backends. Includes full pub/sub
message forwarding via redcon Detach + go-redis PubSub.

Verified all 581 Misskey unit tests pass through the proxy.
@bootjp bootjp requested a review from Copilot March 17, 2026 05:20
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a robust Redis-protocol proxy designed to facilitate the migration of Redis data to an ElasticKV store. It provides a flexible architecture for routing commands, allowing for various stages of migration from simple passthrough to full dual-write with shadow reads. The proxy ensures operational stability through bounded asynchronous operations, comprehensive metrics, and proactive error reporting, making it a critical component for managing data consistency during transitions.

Highlights

  • Dual-Write Redis Proxy: Introduced a new Redis-protocol proxy capable of dual-writing operations to a primary Redis backend and a secondary ElasticKV backend, enabling seamless data migration and consistency checks.
  • Flexible Proxy Modes: Implemented multiple operational modes including 'redis-only', 'dual-write', 'dual-write-shadow', 'elastickv-primary', and 'elastickv-only', allowing administrators to control read/write behavior and migration strategies.
  • Pub/Sub Forwarding: Added support for Redis Pub/Sub commands, forwarding messages and managing dedicated Pub/Sub connections using redcon's Detach functionality and go-redis PubSub.
  • Shadow Reading and Divergence Detection: Incorporated shadow reading capabilities to compare read responses from primary and secondary backends, detecting and classifying data divergences (e.g., migration gaps, data mismatches) for monitoring and debugging.
  • Observability and Error Reporting: Integrated Prometheus metrics for command totals, durations, errors, and divergences, along with Sentry reporting for capturing exceptions and data inconsistencies with de-duplication.
  • Transaction and Blocking Command Handling: Provided specific handling for Redis transactions (MULTI/EXEC/DISCARD) and blocking commands (e.g., BZPOPMIN, XREAD BLOCK), ensuring correct behavior and graceful shutdown integration.
Changelog
  • cmd/redis-proxy/main.go
    • Added new file for the main entry point of the redis-proxy application.
  • proxy/backend.go
    • Added new file defining the Backend interface and its RedisBackend implementation.
  • proxy/command.go
    • Added new file for classifying Redis commands into categories for routing.
  • proxy/compare.go
    • Added new file implementing shadow reading and divergence detection logic.
  • proxy/config.go
    • Added new file defining proxy configuration options and modes.
  • proxy/dualwrite.go
    • Added new file containing the core dual-write and command routing logic.
  • proxy/integration_test.go
    • Added new file with integration tests for the proxy's functionality.
  • proxy/metrics.go
    • Added new file for Prometheus metrics definitions and registration.
  • proxy/proxy.go
    • Added new file implementing the main Redis-protocol proxy server.
  • proxy/proxy_test.go
    • Added new file with unit tests for various proxy components.
  • proxy/pubsub.go
    • Added new file for handling Redis Pub/Sub sessions and message forwarding.
  • proxy/sentry.go
    • Added new file for Sentry error and divergence reporting.
Activity
  • The pull request introduces the initial implementation of the redis-proxy, including all core components, configuration, and testing infrastructure.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive Redis proxy with dual-write capabilities, pub/sub forwarding, metrics, and error reporting. The overall architecture is well-structured, with clear separation of concerns into different packages for configuration, backends, command handling, and proxy logic. The use of a semaphore for bounding asynchronous operations and the detailed command classification are excellent. However, I've identified a few critical issues related to binary data handling that could lead to data corruption, as well as some opportunities for improving graceful shutdown and simplifying transaction handling logic.

Comment thread proxy/compare.go Outdated
Comment thread proxy/dualwrite.go Outdated
Comment thread proxy/proxy.go
Comment thread cmd/redis-proxy/main.go Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new redis-proxy component to the codebase: a Redis-protocol proxy that routes commands to a primary backend and optionally dual-writes / shadow-reads against a secondary backend, with Prometheus metrics and optional Sentry reporting.

Changes:

  • Introduce proxy package implementing command classification/routing, dual-write + shadow-read comparison, and Redis protocol response translation.
  • Add Pub/Sub forwarding support using redcon detached connections bridged to go-redis PubSub.
  • Add unit + integration tests plus a cmd/redis-proxy executable with metrics + Sentry wiring.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
cmd/redis-proxy/main.go CLI entrypoint that wires config, backends, metrics endpoint, and proxy server lifecycle.
proxy/backend.go Backend abstraction and go-redis implementation (including optional PubSub factory).
proxy/command.go Command classification table used to decide routing (read/write/admin/blocking/txn/pubsub/script).
proxy/compare.go Shadow-read comparison logic and divergence classification + reporting.
proxy/config.go Proxy configuration and mode parsing/defaults.
proxy/dualwrite.go Dual-write/shadow-read execution logic, async bounding, metrics, and Sentry reporting hooks.
proxy/integration_test.go End-to-end integration tests against real Redis instances (skipped if unavailable).
proxy/metrics.go Prometheus metrics definitions and registration.
proxy/proxy.go Redcon server implementation: command dispatch, txn handling, pubsub session startup, response encoding.
proxy/proxy_test.go Unit tests covering command classification, divergence logic, dual-write behavior, and Sentry cooldown logic.
proxy/pubsub.go Detached pub/sub session implementation bridging client <-> upstream PubSub.
proxy/sentry.go Sentry reporter wrapper with fingerprint-based cooldown and bounded history tracking.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread proxy/sentry.go
Comment thread proxy/sentry.go
Comment thread proxy/pubsub.go
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/dualwrite.go
Comment thread proxy/dualwrite.go Outdated
Comment thread proxy/proxy.go Outdated
Comment thread proxy/pubsub.go
bootjp and others added 3 commits March 17, 2026 14:28
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Extract dispatchPubSubCommand to reduce readClientCommands complexity (CC=11→8)
- Use metricsSrv.Shutdown for graceful metrics server stop
- Guard against nil logger in NewSentryReporter
- Cap ShouldReport map after eviction to prevent unbounded growth
- Normalize command names with strings.ToUpper in DualWriter methods
- Fix goAsync doc comment to match actual behavior
- Simplify execTxn by merging duplicate result-handling branches
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new Redis-protocol proxy (cmd/redis-proxy) that can route reads/writes across a primary Redis backend and a secondary ElasticKV backend, including optional shadow-read divergence detection, Prometheus metrics, Sentry anomaly reporting, and Pub/Sub forwarding.

Changes:

  • Added a redcon-based proxy server with command classification, transaction handling, and Pub/Sub session bridging.
  • Implemented dual-write + optional shadow-read comparison logic with Prometheus metrics and Sentry reporting.
  • Added unit and integration tests plus a runnable redis-proxy CLI entrypoint.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
cmd/redis-proxy/main.go CLI entrypoint wiring config, metrics server, Sentry, and proxy server lifecycle.
proxy/backend.go Backend abstraction and go-redis based RedisBackend implementation (incl. pipelining + PubSub creation).
proxy/command.go Redis command classification table for routing (read/write/admin/txn/pubsub/etc.).
proxy/compare.go Shadow-read comparison + divergence classification and reporting.
proxy/config.go Proxy configuration and mode parsing/defaults.
proxy/dualwrite.go Dual-write/shadow-read execution, async bounding, and Sentry/metrics instrumentation.
proxy/integration_test.go Integration tests that run against real Redis instances when available.
proxy/metrics.go Prometheus metrics definitions and registration.
proxy/proxy.go Main redcon proxy server: dispatch/routing, txn support, RESP writing, Pub/Sub session startup.
proxy/proxy_test.go Unit tests covering classification, dual-writer behavior, shadow reader, sentry reporter, and backend defaults.
proxy/pubsub.go Detached-connection Pub/Sub session that forwards messages and handles pubsub-mode commands.
proxy/sentry.go Sentry reporter with cooldown-based de-duplication and flush support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread proxy/command.go
Comment thread proxy/compare.go Outdated
Comment thread proxy/sentry.go Outdated
bootjp added 2 commits March 17, 2026 16:49
- Pass []byte directly in bytesArgsToInterfaces instead of converting to string
- Handle []byte type assertion in argsToBytes for correct Sentry reporting
- Fix responseEqual panic when comparing mismatched interface types
- Return false in ShouldReport when at capacity to prevent Sentry flooding
When all subscriptions are removed, the detached connection transitions
to normal command mode instead of being stuck in pub/sub-only mode.
Clients can then execute regular Redis commands (GET, SET, transactions,
etc.) or re-enter pub/sub mode with a new SUBSCRIBE/PSUBSCRIBE.

Key changes:
- Add respWriter interface so writeResponse works with both Conn and DetachedConn
- Refactor pubsubSession with commandLoop that handles both pub/sub and normal modes
- Support transactions (MULTI/EXEC/DISCARD) in normal mode on detached connections
- Track forwardMessages goroutine lifecycle for clean pub/sub mode transitions
- Extract command name constants (MULTI, EXEC, DISCARD, PING, QUIT)
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new redis-proxy component to the codebase that speaks the Redis protocol and routes commands to primary/secondary backends to support dual-write migration to ElasticKV, with observability (Prometheus + Sentry) and pub/sub forwarding.

Changes:

  • Implement Redis-protocol proxy server (redcon) with command classification, transactions, and backend routing (dual-write + optional shadow reads).
  • Add pub/sub bridging using redcon.Detach + go-redis PubSub and support transitioning back to normal command mode.
  • Add Prometheus metrics, Sentry reporting/dedup, and accompanying unit + integration tests; introduce cmd/redis-proxy entrypoint.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
cmd/redis-proxy/main.go New CLI binary wiring config, metrics server, and proxy server lifecycle.
proxy/backend.go Backend abstraction + go-redis implementation, including PubSub capability.
proxy/command.go Command classification table for routing decisions.
proxy/compare.go Shadow-read comparison + divergence classification/metrics/Sentry reporting.
proxy/config.go Proxy configuration + supported operating modes.
proxy/dualwrite.go Core dual-write/shadow-read execution, bounded async work, and metrics/Sentry hooks.
proxy/integration_test.go Optional integration tests against real Redis instances.
proxy/metrics.go Prometheus metric definitions/registration for proxy operations.
proxy/proxy.go redcon server handlers, transaction execution, and RESP response writing helpers.
proxy/proxy_test.go Unit tests covering classification, dual-writer behavior, metrics, and Sentry dedup.
proxy/pubsub.go Pub/sub session implementation with message forwarding and mode switching.
proxy/sentry.go Sentry initialization + cooldown-based dedup for anomaly reporting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread proxy/pubsub.go
Comment thread proxy/sentry.go
Comment thread proxy/proxy.go Outdated
Comment thread proxy/pubsub.go
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/pubsub.go
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/pubsub.go Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Base automatically changed from feature/redis to main March 17, 2026 09:02
bootjp added 3 commits March 17, 2026 19:18
- Fix startForwarding race: capture upstream under lock before goroutine start
- Reject SUBSCRIBE/PSUBSCRIBE during MULTI transaction to prevent state corruption
- Normalize non-redis.Error to "ERR ..." prefix in writeRedisError for valid RESP
- Truncate divergence values in Sentry reports to prevent data leakage
- Add PrimaryDB, PrimaryPassword, SecondaryDB, SecondaryPassword to ProxyConfig
- Add DB and Password fields to BackendOptions, passed to go-redis client
- Add CLI flags: -primary-db, -primary-password, -secondary-db, -secondary-password
- Silently accept SELECT and AUTH commands (return OK without forwarding)
  since DB/auth are configured at the connection-pool level
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Redis-protocol proxy service (redis-proxy) that can route reads/writes across two Redis-protocol backends (Redis + ElasticKV), with optional shadow reads for divergence detection and support for pub/sub forwarding via detached redcon connections.

Changes:

  • Introduces the proxy server core (command classification/routing, dual-write + shadow-read logic, RESP response writer, transaction handling).
  • Adds pub/sub support using redcon.Detach() + go-redis PubSub forwarding, including a “return to normal mode” when unsubscribed.
  • Adds observability: Prometheus metrics + optional Sentry reporting, plus unit/integration tests for non-pubsub behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
cmd/redis-proxy/main.go CLI entrypoint wiring config, backends, metrics endpoint, and graceful shutdown.
proxy/backend.go Backend abstraction and go-redis implementation (including a dedicated PubSub connection).
proxy/command.go Redis command classification table for routing decisions.
proxy/config.go Proxy config + modes (redis-only, dual-write, shadow, elastickv-primary/only).
proxy/dualwrite.go Dual-writer/shadow-reader execution paths + bounded async work.
proxy/compare.go Shadow-read comparison, divergence classification, and divergence reporting hook.
proxy/metrics.go Prometheus metrics definitions/registration.
proxy/sentry.go Optional Sentry reporter with cooldown-based de-duplication support.
proxy/proxy.go redcon server, RESP writing helpers, command dispatch, and transaction support.
proxy/pubsub.go Detached pub/sub session implementation and upstream message forwarding.
proxy/proxy_test.go Unit tests for core proxy components (classification, dual-write, sentry gating, etc.).
proxy/integration_test.go Integration tests against real Redis instances for basic command flows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread proxy/sentry.go
Comment thread proxy/proxy.go
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/pubsub.go Outdated
Comment thread proxy/pubsub.go
bootjp and others added 2 commits March 20, 2026 17:28
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Comment thread proxy/shadow_pubsub.go Outdated
Comment thread proxy/shadow_pubsub.go Outdated
Comment thread proxy/pubsub_test.go
@bootjp
Copy link
Copy Markdown
Owner Author

bootjp commented Mar 20, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 20, 2026

@bootjp I've opened a new pull request, #365, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 3 commits March 20, 2026 08:42
… panic

Co-authored-by: bootjp <1306365+bootjp@users.noreply.github.com>
Co-authored-by: bootjp <1306365+bootjp@users.noreply.github.com>
Fix matchSecondary window scan, boundary consistency, and SELECT test panic
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.

Comment thread proxy/pubsub.go Outdated
Comment thread proxy/shadow_pubsub_test.go Outdated
@bootjp
Copy link
Copy Markdown
Owner Author

bootjp commented Mar 20, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 20, 2026

@bootjp I've opened a new pull request, #366, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits March 20, 2026 09:09
…leEntry test

Co-authored-by: bootjp <1306365+bootjp@users.noreply.github.com>
fix: deterministic writeUnsubAll ordering + fix MatchSecondaryMiddleEntry test coverage
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.

Comment thread proxy/proxy.go Outdated
Comment thread proxy/pubsub.go Outdated
bootjp and others added 2 commits March 20, 2026 18:18
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@bootjp bootjp enabled auto-merge March 20, 2026 09:20
Comment thread proxy/proxy.go
// uses a shared connection pool and cannot maintain per-client DB state.
if name == "SELECT" {
// Redis arity: SELECT <db>. Require exactly one DB argument.
if len(args) != 2 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
Magic number: 2, in detected (mnd)

Comment thread proxy/pubsub.go
return false
}
// Enforce Redis arity: SELECT requires exactly one DB index argument.
if len(args) != 2 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
Magic number: 2, in detected (mnd)

@bootjp bootjp merged commit 8d98c59 into main Mar 20, 2026
7 checks passed
@bootjp bootjp deleted the feature/redis-proxy branch March 20, 2026 09:21
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.

3 participants