A small Redis/Valkey client library written in Odin.
This codebase was created by Codex and reviewed/checked by the author.
That means:
- the implementation was generated and iterated on by Codex
- the project direction, validation, and final review were provided by the author
- TCP connection to Redis-compatible servers
- optional
AUTHduring connect - optional
SELECTduring connect - RESP parsing for:
- simple strings
- errors
- integers
- bulk strings
- arrays
- null values
- convenience commands:
PINGGETSETSET ... EXDEL
- generic
commandAPI for custom Redis commands - example program with leak tracking
- automated tests, including randomized round-trip tests
redis.odin: library implementationredis_test.odin: automated testsexamples/verify_localhost.odin: example against a local Redis/Valkey serverexamples/reuse_reply_allocator.odin: example that resets the same reply allocator between commandsexamples/set_ex_separate_allocators.odin: example that usesset_exwith implicit client allocator and explicit reply allocatorMakefile: basic project commands
package main
import "core:fmt"
import "core:mem"
import vmem "core:mem/virtual"
import redis ".."
main :: proc() {
reply_arena: vmem.Arena
if arena_err := vmem.arena_init_growing(&reply_arena); arena_err != nil {
fmt.println("arena init error:", arena_err)
return
}
defer vmem.arena_destroy(&reply_arena)
reply_allocator := vmem.arena_allocator(&reply_arena)
client, err := redis.connect(redis.Config{
address = "127.0.0.1:6379",
})
if err != .None {
fmt.println("connect error:", err)
return
}
defer redis.close(&client)
reply, cmd_err := redis.set_ex(&client, "hello", "world", 60, reply_allocator)
if cmd_err != .None {
fmt.println("command error:", cmd_err)
return
}
fmt.println(reply.kind, reply.text, reply.integer)
mem.free_all(reply_allocator)
}destroy_reply is still available for fine-grained cleanup, but it now accepts an explicit allocator:
redis.destroy_reply(&reply, reply_allocator)If you want to reuse the same allocator across multiple commands, the intended pattern is:
mem.free_all(reply_allocator)
reply, err := redis.get(&client, "hello", reply_allocator)After free_all, all previously returned replies allocated from reply_allocator are invalid and must not be used again. A complete runnable example is available in examples/reuse_reply_allocator.odin.
The repository includes a minimal Makefile.
make check
make test
make tags
make formatEquivalent commands:
odin check . -no-entry-point
odin test .
otag .
odinfmt -w .Start a local Redis or Valkey server on 127.0.0.1:6379, then run:
odin run examples/verify_localhost.odin -fileThe example performs a small end-to-end verification and checks for memory leaks with Odin's tracking allocator.
To run the per-request allocator reuse example:
odin run examples/reuse_reply_allocator.odin -fileTo run the set_ex example that keeps the client allocator separate from the reply allocator:
odin run examples/set_ex_separate_allocators.odin -fileWith a local Redis or Valkey instance listening on 127.0.0.1:6379:
odin test .To run a single test:
odin test . -define:ODIN_TEST_NAMES=redis.test_random_roundtrip_has_no_leakscommandreturns aReplyeven when Redis returns an error reply- in that case the returned error is
redis.Error.Server_Error - the raw server message is available in both
reply.textandclient.last_server_error
This project is licensed under the MIT License. See LICENSE.md for details.