3 Commits

Author SHA1 Message Date
hellerve fafa2b40d2 use new sockets lib 2026-04-11 11:20:25 +02:00
hellerve 692fe51728 update docs 2026-04-03 11:37:12 +02:00
hellerve d88b0631a6 clarify redis version 2026-04-03 11:07:53 +02:00
6 changed files with 129 additions and 25 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ A Redis client library for Carp, supporting Redis 7.x.
## Installation
```clojure
(load "https://git.veitheller.de/carpentry/redis.git@master")
(load "https://git.veitheller.de/carpentry/redis.git@0.2.0")
```
## Usage
+19
View File
@@ -40,6 +40,25 @@ Protocol</a>. You can create all types,
stringify the built types into strings using <a href="#str"><code>str</code></a>, and decode from
the string protocol using <a href="#from-string"><code>from-string</code></a>. Arrays are fully
supported, including nested arrays.</p>
<pre><code>; decoding
(RESP.from-string &quot;+OK\r\n&quot;) ; =&gt; (Success (Str @&quot;OK&quot;))
(RESP.from-string &quot;:42\r\n&quot;) ; =&gt; (Success (Integer 42))
(RESP.from-string &quot;$-1\r\n&quot;) ; =&gt; (Success (Null))
; encoding
(str &amp;(RESP.Str @&quot;hi&quot;)) ; =&gt; &quot;$2\r\nhi\r\n&quot;
(str &amp;(RESP.Integer 42)) ; =&gt; &quot;:42\r\n&quot;
; pattern matching on responses
(match (Redis.get &amp;r @&quot;key&quot;)
(Result.Success resp)
(match resp
(RESP.Str s) (println* &quot;got: &quot; &amp;s)
(RESP.Null) (println* &quot;not found&quot;)
(RESP.Arr items) (println* &quot;array of &quot; &amp;(Int.str (Array.length &amp;items)))
_ (println* &quot;other&quot;))
(Result.Error e) (println* &quot;error: &quot; &amp;e))
</code></pre>
<p>If you want your types to be supported when encoding, youll have to implement
the interface <code>to-redis</code>, the signature of which is <code>(Fn [a] RESP))</code>.</p>
+15 -7
View File
@@ -38,8 +38,16 @@
<p>is a wrapper around Redis connections. It supports opening a
connection using <a href="#open"><code>open</code></a> or <a href="#open-on"><code>open-on</code></a>, reading from and
sending to the connection (using <a href="#read"><code>read</code></a> and <a href="#send"><code>send</code></a>,
respectively), and contains thin wrappers around all Redis commands (everything
else).</p>
respectively), and contains thin wrappers around all Redis commands through 7.2.</p>
<pre><code>(match (Redis.open &quot;127.0.0.1&quot;)
(Result.Success r)
(do
(println* &amp;(Redis.set &amp;r @&quot;key&quot; @&quot;val&quot;))
(println* &amp;(Redis.get &amp;r @&quot;key&quot;))
(println* &amp;(Redis.lrange &amp;r @&quot;list&quot; @&quot;0&quot; @&quot;-1&quot;))
(Redis.close r))
(Result.Error err) (IO.errorln &amp;err))
</code></pre>
</div>
<div class="binder">
@@ -3095,7 +3103,7 @@ else).</p>
instantiate
</div>
<p class="sig">
(Fn [Socket] Redis)
(Fn [TcpStream] Redis)
</p>
<span>
@@ -4980,7 +4988,7 @@ else).</p>
instantiate
</div>
<p class="sig">
(Fn [Redis, Socket] Redis)
(Fn [Redis, TcpStream] Redis)
</p>
<span>
@@ -5000,7 +5008,7 @@ else).</p>
instantiate
</div>
<p class="sig">
(Fn [(Ref Redis a), Socket] ())
(Fn [(Ref Redis a), TcpStream] ())
</p>
<span>
@@ -5314,7 +5322,7 @@ else).</p>
instantiate
</div>
<p class="sig">
(Fn [(Ref Redis a)] (Ref Socket a))
(Fn [(Ref Redis a)] (Ref TcpStream a))
</p>
<span>
@@ -5816,7 +5824,7 @@ else).</p>
instantiate
</div>
<p class="sig">
(Fn [Redis, (Ref (Fn [Socket] Socket a) b)] Redis)
(Fn [Redis, (Ref (Fn [TcpStream] TcpStream a) b)] Redis)
</p>
<span>
+21 -2
View File
@@ -30,8 +30,27 @@
<h1>
redis
</h1>
<p>is a Redis client library for Carp.</p>
<pre><code>(load &quot;https://git.veitheller.de/carpentry/redis.git@master&quot;)
<p>is a Redis client library for Carp, supporting Redis 7.x.</p>
<h2>Installation</h2>
<pre><code>(load &quot;https://git.veitheller.de/carpentry/redis.git@0.2.0&quot;)
</code></pre>
<h2>Example</h2>
<pre><code>(defn main []
(match (Redis.open &quot;127.0.0.1&quot;)
(Result.Success r)
(do
(println* &amp;(Redis.set &amp;r @&quot;key&quot; @&quot;value&quot;))
(println* &amp;(Redis.get &amp;r @&quot;key&quot;))
(println* &amp;(Redis.lrange &amp;r @&quot;mylist&quot; @&quot;0&quot; @&quot;-1&quot;))
(match (Redis.get &amp;r @&quot;key&quot;)
(Result.Success resp)
(match resp
(RESP.Str s) (println* &quot;got: &quot; &amp;s)
(RESP.Null) (println* &quot;not found&quot;)
_ (println* &quot;unexpected type&quot;))
(Result.Error e) (println* &quot;error: &quot; &amp;e))
(Redis.close r))
(Result.Error err) (IO.errorln &amp;err)))
</code></pre>
</div>
+25 -2
View File
@@ -5,10 +5,33 @@
(Project.config "docs-logo" "")
(Project.config "docs-url" "https://git.veitheller.de/carpentry/redis")
(Project.config "docs-styling" "../style.css")
(Project.config "docs-prelude" "is a Redis client library for Carp.
(Project.config "docs-prelude" "is a Redis client library for Carp, supporting Redis 7.x.
## Installation
```
(load \"https://git.veitheller.de/carpentry/redis.git@master\")
(load \"https://git.veitheller.de/carpentry/redis.git@0.2.0\")
```
## Example
```
(defn main []
(match (Redis.open \"127.0.0.1\")
(Result.Success r)
(do
(println* &(Redis.set &r @\"key\" @\"value\"))
(println* &(Redis.get &r @\"key\"))
(println* &(Redis.lrange &r @\"mylist\" @\"0\" @\"-1\"))
(match (Redis.get &r @\"key\")
(Result.Success resp)
(match resp
(RESP.Str s) (println* \"got: \" &s)
(RESP.Null) (println* \"not found\")
_ (println* \"unexpected type\"))
(Result.Error e) (println* \"error: \" &e))
(Redis.close r))
(Result.Error err) (IO.errorln &err)))
```
")
+48 -13
View File
@@ -1,4 +1,4 @@
(load "git@github.com:carpentry-org/sockets@0.0.2")
(load "git@github.com:carpentry-org/socket@0.1.1")
(deftype RESP
(Null [])
@@ -117,18 +117,17 @@
)
(deftype Redis [
sock Socket
sock TcpStream
])
(defmodule Redis
(use-all Array Result Socket)
(use-all Array Result)
(doc open-on "opens the connection to Redis on port `port`.")
(defn open-on [host port]
(let [s (setup-client host port)]
(if (valid? &s)
(Success (init s))
(Error (fmt "Couldnt connect to %s:%d" host port)))))
(match (TcpStream.connect host port)
(Result.Success s) (Success (init s))
(Result.Error e) (Error (fmt "Couldnt connect to %s:%d: %s" host port &e))))
(doc open "opens the connection to Redis on port 6379.
@@ -136,14 +135,19 @@ For variable port numbers please check out [`open-on`](#open-on).")
(defn open [host] (open-on host 6379))
(doc read "reads a `RESP` object from Redis.")
(defn read [r] (RESP.from-string &(Socket.read (sock r))))
(defn read [r]
(match (the (Result String String) (TcpStream.read (sock r)))
(Result.Success s) (RESP.from-string &s)
(Result.Error e) (Error e)))
(doc send "sends the command `cmd` with the arguments `args` to Redis.")
(defn send [r cmd args]
(let [cmd-parts (copy-map &(fn [x] (Box.init (to-redis @x))) &(Pattern.split #" " &cmd))]
(Socket.send (sock r) &(str &(RESP.Arr (concat &[cmd-parts (copy-map &(fn [x] (Box.init @x)) args)]))))))
(let [cmd-parts (copy-map &(fn [x] (Box.init (to-redis @x))) &(Pattern.split #" " &cmd))
msg (str &(RESP.Arr (concat &[cmd-parts (copy-map &(fn [x] (Box.init @x)) args)])))]
(ignore (TcpStream.send (sock r) &msg))))
(doc close "closes the connection to Redis.")
(defn close [r] (Socket.close @(sock &r)))
(defn close [r] (TcpStream.close @(sock &r)))
)
(defndynamic rtreat- [s]
@@ -503,13 +507,44 @@ It takes the same arguments as the [Redis command](https://redis.io/commands/"
(doc Redis "is a wrapper around Redis connections. It supports opening a
connection using [`open`](#open) or [`open-on`](#open-on), reading from and
sending to the connection (using [`read`](#read) and [`send`](#send),
respectively), and contains thin wrappers around all Redis commands (everything
else).")
respectively), and contains thin wrappers around all Redis commands through 7.2.
```
(match (Redis.open \"127.0.0.1\")
(Result.Success r)
(do
(println* &(Redis.set &r @\"key\" @\"val\"))
(println* &(Redis.get &r @\"key\"))
(println* &(Redis.lrange &r @\"list\" @\"0\" @\"-1\"))
(Redis.close r))
(Result.Error err) (IO.errorln &err))
```")
(doc RESP "is a wrapper around the [Redis Serialization
Protocol](https://redis.io/topics/protocol). You can create all types,
stringify the built types into strings using [`str`](#str), and decode from
the string protocol using [`from-string`](#from-string). Arrays are fully
supported, including nested arrays.
```
; decoding
(RESP.from-string \"+OK\\r\\n\") ; => (Success (Str @\"OK\"))
(RESP.from-string \":42\\r\\n\") ; => (Success (Integer 42))
(RESP.from-string \"$-1\\r\\n\") ; => (Success (Null))
; encoding
(str &(RESP.Str @\"hi\")) ; => \"$2\\r\\nhi\\r\\n\"
(str &(RESP.Integer 42)) ; => \":42\\r\\n\"
; pattern matching on responses
(match (Redis.get &r @\"key\")
(Result.Success resp)
(match resp
(RESP.Str s) (println* \"got: \" &s)
(RESP.Null) (println* \"not found\")
(RESP.Arr items) (println* \"array of \" &(Int.str (Array.length &items)))
_ (println* \"other\"))
(Result.Error e) (println* \"error: \" &e))
```
If you want your types to be supported when encoding, youll have to implement
the interface `to-redis`, the signature of which is `(Fn [a] RESP))`.")