Skip to content

Commit e3fc32b

Browse files
authored
Add command builder primitives and response extraction helpers (#17)
* Add command builder primitives and response extraction helpers Six command builder primitives (RedisServer, RedisString, RedisKey, RedisHash, RedisList, RedisSet) replace raw Array[ByteSeq] val construction for common Redis commands. Each method is a pure function returning Array[ByteSeq] val, using ByteSeq parameters to accept both String and Array[U8] val inputs. RespConvert provides total functions for extracting typed values from RespValue responses with a three-way return: the extracted value for matching types, RespNull for null input, or None for type mismatches. This replaces nested pattern matching on RespValue variants. Tests include 11 property tests for RespConvert (one per extractor), 9 property tests for variadic command builders, 8 example test classes, and an integration test exercising the full roundtrip against Redis. Design: #16 * Add RespVerbatimString to as_bytes Aligns with the Discussion #16 design. Users wanting raw bytes from a VerbatimString no longer need to pattern-match directly. * Remove release notes (pre-1.0)
1 parent dc14c85 commit e3fc32b

14 files changed

Lines changed: 1631 additions & 11 deletions

CLAUDE.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ Package: `redis`
5050
- `_BuildHelloCommand` / `_BuildAuthCommand` (primitives in `session.pony`): Build HELLO 3 and AUTH commands for protocol negotiation and authentication.
5151
- `_IllegalState` / `_Unreachable` (in `_mort.pony`): Primitives for detecting impossible states.
5252

53+
### Command Builders
54+
55+
Six public primitives for constructing common Redis commands as `Array[ByteSeq] val`. Each method is a pure function.
56+
57+
- `RedisServer` (in `redis_server.pony`): PING, ECHO, DBSIZE, FLUSHDB.
58+
- `RedisString` (in `redis_string.pony`): GET, SET (with NX/EX variants), INCR, DECR, INCRBY, DECRBY, MGET, MSET.
59+
- `RedisKey` (in `redis_key.pony`): DEL, EXISTS, EXPIRE, TTL, PERSIST, KEYS, RENAME, TYPE (as `type_of`).
60+
- `RedisHash` (in `redis_hash.pony`): HGET, HSET, HDEL, HGETALL, HEXISTS.
61+
- `RedisList` (in `redis_list.pony`): LPUSH, RPUSH, LPOP, RPOP, LLEN, LRANGE.
62+
- `RedisSet` (in `redis_set.pony`): SADD, SREM, SMEMBERS, SISMEMBER, SCARD.
63+
64+
Fixed-argument commands use `recover val [as ByteSeq: ...] end`. Variadic commands use `recover val` with `Array.push` loops.
65+
66+
### Response Extraction
67+
68+
- `RespConvert` (primitive in `resp_convert.pony`): Total functions for extracting typed values from `RespValue`. Each extractor returns `(T | RespNull | None)` except `as_error``(String | None)` and `is_ok``Bool`. Methods: `as_string`, `as_bytes`, `as_integer`, `as_bool`, `as_array`, `as_double`, `as_big_number`, `as_map`, `as_set`, `as_error`, `is_ok`.
69+
5370
### SSL/TLS
5471

5572
- `SSLMode` (type alias in `ssl_mode.pony`): `(SSLDisabled | SSLRequired)`. Controls whether the session uses plaintext TCP or SSL/TLS.

examples/basic/main.pony

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ actor Client is (SessionStatusNotify & ResultReceiver)
2222

2323
be redis_session_ready(session: Session) =>
2424
_out.print("Connected and ready.")
25-
let cmd: Array[ByteSeq] val = ["SET"; "hello"; "world"]
26-
session.execute(cmd, this)
25+
session.execute(RedisString.set("hello", "world"), this)
2726

2827
be redis_session_connection_failed(session: Session) =>
2928
_out.print("Failed to connect.")
3029

3130
be redis_response(session: Session, response: RespValue) =>
32-
match response
33-
| let s: RespSimpleString => _out.print("Response: " + s.value)
34-
| let e: RespError => _out.print("Error: " + e.message)
31+
if RespConvert.is_ok(response) then
32+
_out.print("Response: OK")
33+
else
34+
match RespConvert.as_error(response)
35+
| let msg: String => _out.print("Error: " + msg)
36+
end
3537
end
3638
_session.close()
3739

redis/_test.pony

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,49 @@ actor \nodoc\ Main is TestList
7171
// Command construction unit tests
7272
test(_TestBuildHelloCommand)
7373
test(_TestBuildAuthCommand)
74+
75+
// RespConvert property tests
76+
test(Property1UnitTest[RespValue](_TestRespConvertAsString))
77+
test(Property1UnitTest[RespValue](_TestRespConvertAsBytes))
78+
test(Property1UnitTest[RespValue](_TestRespConvertAsInteger))
79+
test(Property1UnitTest[RespValue](_TestRespConvertAsBool))
80+
test(Property1UnitTest[RespValue](_TestRespConvertAsArray))
81+
test(Property1UnitTest[RespValue](_TestRespConvertAsDouble))
82+
test(Property1UnitTest[RespValue](_TestRespConvertAsBigNumber))
83+
test(Property1UnitTest[RespValue](_TestRespConvertAsMap))
84+
test(Property1UnitTest[RespValue](_TestRespConvertAsSet))
85+
test(Property1UnitTest[RespValue](_TestRespConvertAsError))
86+
test(Property1UnitTest[RespValue](_TestRespConvertIsOk))
87+
88+
// RespConvert example tests
89+
test(_TestRespConvertIsOkExamples)
90+
test(_TestRespConvertAsErrorBulkExample)
91+
92+
// Command builder property tests
93+
test(Property1UnitTest[Array[String] val](_TestRedisKeyDelProperty))
94+
test(Property1UnitTest[Array[String] val](_TestRedisKeyExistsProperty))
95+
test(Property1UnitTest[Array[String] val](
96+
_TestRedisStringMgetProperty))
97+
test(Property1UnitTest[(String, Array[String] val)](
98+
_TestRedisListLpushProperty))
99+
test(Property1UnitTest[(String, Array[String] val)](
100+
_TestRedisListRpushProperty))
101+
test(Property1UnitTest[(String, Array[String] val)](
102+
_TestRedisSetSaddProperty))
103+
test(Property1UnitTest[(String, Array[String] val)](
104+
_TestRedisSetSremProperty))
105+
test(Property1UnitTest[(String, Array[String] val)](
106+
_TestRedisHashHdelProperty))
107+
test(Property1UnitTest[Array[(String, String)] val](
108+
_TestRedisStringMsetProperty))
109+
110+
// Command builder example tests
111+
test(_TestRedisServerExamples)
112+
test(_TestRedisStringExamples)
113+
test(_TestRedisKeyExamples)
114+
test(_TestRedisHashExamples)
115+
test(_TestRedisListExamples)
116+
test(_TestRedisSetExamples)
117+
118+
// Command API integration test
119+
test(_TestCommandApiSetAndGet)

0 commit comments

Comments
 (0)