Skip to content

feat: instrument RedisCluster and ClusterPipeline for record/replay#91

Merged
sohankshirsagar merged 5 commits intomainfrom
sohan/redis-cluster-fix
Apr 11, 2026
Merged

feat: instrument RedisCluster and ClusterPipeline for record/replay#91
sohankshirsagar merged 5 commits intomainfrom
sohan/redis-cluster-fix

Conversation

@sohankshirsagar
Copy link
Copy Markdown
Contributor

Summary

redis.cluster.RedisCluster.execute_command is a completely separate method from redis.Redis.execute_command and does not inherit or delegate to it. This means any Redis command routed through the cluster client bypassed the SDK's record/replay interception entirely, causing PermissionError crashes during replay when the cluster client attempted real TCP connections to production node addresses.

This change patches RedisCluster.execute_command and ClusterPipeline.execute (both sync and async variants) so that cluster-routed commands are properly intercepted during record and replayed from mocks.

Changes

  • Patch redis.cluster.RedisCluster.execute_command (sync) to route through _traced_execute_command, matching the existing redis.Redis instrumentation pattern
  • Patch redis.cluster.ClusterPipeline.execute (sync) with a dedicated _traced_cluster_pipeline_execute that snapshots the command queue before execution (ClusterPipeline resets the queue in its finally block)
  • Patch redis.asyncio.cluster.RedisCluster.execute_command (async) to route through _traced_async_execute_command
  • Patch redis.asyncio.cluster.ClusterPipeline.execute (async) with _traced_async_cluster_pipeline_execute
  • Update _get_pipeline_commands to handle ClusterPipeline's different command storage: _execution_strategy._command_queue (sync) and _command_queue (async)
  • Add Redis Cluster e2e test infrastructure: 3-node Redis Cluster in Docker Compose with automatic cluster initialization
  • Add cluster test endpoints: /test/cluster-set-get, /test/cluster-incr, /test/cluster-pipeline exercising RedisCluster.execute_command and ClusterPipeline.execute
  • Add cluster requests to test runner to include cluster operations in the e2e record/replay cycle

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ec0858f. Configure here.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="drift/instrumentation/redis/instrumentation.py">

<violation number="1" location="drift/instrumentation/redis/instrumentation.py:1125">
P2: Avoid coercing integer-valued floats to int during replay deserialization; it changes response types and can make replay behavior differ from recorded Redis responses.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

@tusk-dev
Copy link
Copy Markdown
Contributor

tusk-dev bot commented Apr 11, 2026

Generated 30 tests - 30 passed

Commit tests View tests

Tip

New to Tusk Unit Tests? Learn more here.

Test Summary

  • RedisInstrumentation._deserialize_value - 8 ✓
  • RedisInstrumentation._get_pipeline_commands - 6 ✓
  • RedisInstrumentation._serialize_value - 9 ✓
  • RedisInstrumentation._traced_async_cluster_pipeline_execute - 3 ✓
  • RedisInstrumentation._traced_cluster_pipeline_execute - 4 ✓

Results

Tusk's tests are all passing and cover the critical paths for Redis Cluster instrumentation. The test suite validates that _serialize_value and _deserialize_value correctly handle type preservation (floats, bytes, nested lists) through record/replay cycles—essential since JSON serialization loses type information. The _get_pipeline_commands tests confirm the instrumentation can extract commands from both standard Pipeline (command_stack) and ClusterPipeline objects (sync: _execution_strategy._command_queue, async: _command_queue directly), with proper prioritization when multiple attributes exist. The _traced_cluster_pipeline_execute and _traced_async_cluster_pipeline_execute tests verify that cluster pipeline execution correctly snapshots the command queue before it's cleared, then routes through the appropriate mode handler (DISABLED bypasses instrumentation, RECORD captures commands, REPLAY mocks responses). This matters because RedisCluster.execute_command is a completely separate code path from redis.Redis.execute_command and was previously bypassing interception entirely—these tests ensure cluster operations now integrate seamlessly into the record/replay system.

View check history

Commit Unit Tests Created (UTC)
e8057f0 15 ✓, 0 ✗ · Tests Apr 10, 2026 11:06PM
ec0858f 26 ✓, 0 ✗ · Tests Apr 11, 2026 1:06AM
066eaa2 26 ✓, 0 ✗ · Tests Apr 11, 2026 1:15AM
0fca713 30 ✓, 0 ✗ · Tests Apr 11, 2026 1:44AM

Was Tusk helpful? Give feedback by reacting with 👍 or 👎

@sohankshirsagar sohankshirsagar merged commit c48dd78 into main Apr 11, 2026
27 checks passed
@sohankshirsagar sohankshirsagar deleted the sohan/redis-cluster-fix branch April 11, 2026 06:58
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.

2 participants