Skip to content

Commit 352ebcc

Browse files
author
codeErrorSleep
committed
docs: add redis backend phase 1 refactor design
1 parent a700015 commit 352ebcc

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Redis Backend Phase 1 Refactor Design
2+
3+
## Context
4+
5+
`src-tauri/src/datasources/redis.rs` is over 3,600 lines and mixes connection
6+
setup, Redis command execution, key scanning, typed key operations, stream
7+
logic, sorted set helpers, geo helpers, server metadata, raw console execution,
8+
DTOs, and string-based error handling. `src-tauri/src/commands/redis.rs` is over
9+
1,200 lines and mixes Tauri command boundaries with connection cache/retry
10+
logic and command log handling.
11+
12+
Existing Rust integration tests import `dbpaw_lib::datasources::redis::*`
13+
directly. The frontend calls fixed Tauri command names through
14+
`src/services/api.ts`. Phase 1 must therefore keep public behavior and public
15+
paths stable while reducing backend module size and stopping further Redis
16+
string-error growth.
17+
18+
## Goals
19+
20+
- Keep all Tauri command names, signatures, and frontend TypeScript wrappers
21+
unchanged.
22+
- Keep `dbpaw_lib::datasources::redis::*` usable for existing integration tests.
23+
- Split Redis datasource internals by responsibility.
24+
- Introduce Redis-specific error conversion so new and moved datasource code can
25+
use structured errors internally.
26+
- Convert Redis errors to `String` only at the command boundary.
27+
- Preserve current Redis runtime behavior, including standalone, cluster, and
28+
sentinel connection behavior.
29+
30+
## Non-Goals
31+
32+
- Do not redesign the Redis UI or TypeScript service API.
33+
- Do not rename existing Tauri commands.
34+
- Do not change Redis integration test semantics.
35+
- Do not introduce a new Redis driver trait or broader datasource abstraction.
36+
- Do not fully rewrite command registration in `src-tauri/src/lib.rs`.
37+
38+
## Architecture
39+
40+
`src-tauri/src/datasources/redis.rs` remains the public facade module. It will
41+
declare private or crate-visible submodules under `src-tauri/src/datasources/redis/`
42+
and re-export the same public types and functions currently used by tests and
43+
commands.
44+
45+
Planned datasource modules:
46+
47+
- `connection.rs`: `RedisConnection`, connection cache handle types, standalone,
48+
cluster, and sentinel connection construction, database selection, host parsing,
49+
timeout handling, and low-level query helpers.
50+
- `error.rs`: `RedisError`, `RedisResult<T>`, conversion from
51+
`redis::RedisError`, validation failures, scan cursor failures, unsupported
52+
cluster routing, and conversion into `AppError` or final command-boundary text.
53+
- `models.rs`: DTOs, payloads, enums, and result structs.
54+
- `scan.rs`: standalone scan, cluster scan, cursor encoding/decoding, cluster
55+
master discovery, node address parsing, wildcard guard, and key metadata lookup.
56+
- `key_value.rs`: key validation, get/set/page/patch/delete/rename/ttl, bitmap,
57+
HyperLogLog, set/list helpers, and batch mget/mset/key operations.
58+
- `stream.rs`: stream entry parsing, stream view/range, groups, ack, pending,
59+
claim, trim, and readgroup operations.
60+
- `zset.rs`: sorted set score, rank, range by score, range by lex, lex count,
61+
pop min, and pop max operations.
62+
- `geo.rs`: geo add, position, distance, and search operations.
63+
- `server.rs`: server info, config, slowlog, and cluster info parsing.
64+
- `raw.rs`: raw command tokenization, Redis value formatting, and raw execution.
65+
66+
The facade should make call sites continue to look like:
67+
68+
```rust
69+
use dbpaw_lib::datasources::redis;
70+
71+
let mut conn = redis::connect(&form, None).await?;
72+
let value = redis::get_key(&mut conn, key).await?;
73+
```
74+
75+
## Command Boundary
76+
77+
`src-tauri/src/commands/redis.rs` keeps all existing `#[tauri::command]`
78+
functions and return shapes. The command file may get a small private submodule
79+
or helper extraction for cache/retry logic, but Phase 1 does not split commands
80+
into multiple public command modules.
81+
82+
The command layer remains responsible for:
83+
84+
- Loading a `ConnectionForm` from `AppState`.
85+
- Acquiring or creating cached Redis connections.
86+
- Retrying once after Redis IO-style connection failures.
87+
- Converting datasource errors into `String` for Tauri.
88+
- Appending raw console command logs.
89+
90+
## Error Handling
91+
92+
New datasource internals should return `RedisResult<T>` instead of
93+
`Result<T, String>`. `RedisError` should cover at least:
94+
95+
- Redis server/client errors from `redis::RedisError`.
96+
- Validation errors such as empty keys or invalid write payloads.
97+
- Invalid database selection.
98+
- Invalid scan cursor.
99+
- Unsupported routing or command behavior for cluster mode.
100+
- Parse/format errors that are internal to Redis response handling.
101+
102+
`RedisError` converts into `AppError` using existing categories:
103+
104+
- Connection and IO failures map to `AppError::ConnectionFailed` or timeout/auth
105+
variants when the source clearly indicates that class.
106+
- Redis command failures map to `AppError::query_failed`.
107+
- User input and cursor validation failures map to `AppError::validation`.
108+
- Unsupported cluster/command behavior maps to `AppError::unsupported`.
109+
- Unexpected parse/state failures map to `AppError::internal`.
110+
111+
The command boundary converts `RedisError` to `String` via `AppError`, matching
112+
the project rule that structured errors cross the backend from the inside out.
113+
During Phase 1, legacy helper functions may temporarily retain `Result<T, String>`
114+
behind the facade where required to keep the refactor mechanical, but newly
115+
moved code should not add new string tags such as `[REDIS_ERROR]` or
116+
`[REDIS_SCAN_ERROR]`.
117+
118+
IO retry detection should move away from parsing `[REDIS_ERROR]` prefixes and
119+
toward a Redis-specific predicate on `RedisError`. Existing retry unit tests
120+
should be updated to assert the typed predicate.
121+
122+
## Testing
123+
124+
Minimum verification after Rust changes:
125+
126+
- Run targeted Redis command/helper tests if present.
127+
- Run `cargo check` from `src-tauri` before declaring completion.
128+
129+
Additional verification when local dependencies allow it:
130+
131+
- Run Redis integration tests that use `src-tauri/tests/redis_integration.rs`.
132+
- Use `IT_REUSE_LOCAL_DB=1` when iterating against an already-running Redis
133+
instance.
134+
135+
Because Redis integration tests may require Docker or local Redis services,
136+
failure to run them should be reported explicitly rather than hidden.
137+
138+
## Migration Strategy
139+
140+
1. Add `src-tauri/src/datasources/redis/` modules and move types/functions in
141+
small responsibility groups.
142+
2. Keep `src-tauri/src/datasources/redis.rs` as the facade and re-export
143+
existing public API.
144+
3. Add `RedisError` and migrate the connection/query helpers first, because most
145+
other modules depend on them.
146+
4. Migrate scan, key/value, stream, zset, geo, server, and raw modules one group
147+
at a time.
148+
5. Update `commands/redis.rs` helpers to consume typed Redis errors internally
149+
while returning `String` from Tauri commands.
150+
6. Run formatting and Rust verification after each meaningful group or at least
151+
before final completion.
152+
153+
## Risks
154+
155+
- Moving many functions can accidentally change visibility. The facade should
156+
re-export deliberately and tests should continue importing through the old
157+
path.
158+
- Redis cluster and sentinel behavior is more fragile than standalone behavior.
159+
Connection code should be moved before behavior is changed, and cluster-specific
160+
helpers should remain covered by existing integration tests where available.
161+
- Full error migration may be too large for one mechanical pass. The acceptable
162+
Phase 1 fallback is to introduce the typed error path at core connection/query
163+
boundaries and prevent new string-tag protocols while leaving isolated legacy
164+
conversions for later cleanup.

0 commit comments

Comments
 (0)