aboutsummaryrefslogtreecommitdiff
path: root/README.redis
blob: 1b66eda60805e8c4a2b09eb329a0acd0c3caaa6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Jim redis extension documentation.

Overview
~~~~~~~~

The redis extension is a very simple extension to provide fast
client access to redis (https://redis.io/) via the hiredis library
(which must be available when building).

Usage
~~~~~

The redis extension exports an Object Based interface. In order
to open a connection, a stream socket must be open to the redis server.
e.g.

    set r [redis [socket stream localhost:6379]]

Or to connect via the unix domain socket:

    set r [redis [socket unix /tmp/redis.sock]]

The [redis] command returns a handle, that is a command name that
can be used to perform operations on the redis instance. For example:

    . package require redis
    1.0
    . set r [redis [socket stream localhost:6379]]
    ::redis.handle4
    . $r KEYS a*
    abc
    . $r SET def 3
    OK
    . $r INCR def
    4
    . $r HMSET hash a 1 b 2 c 3
    OK
    . $r HGETALL hash
    a 1 b 2 c 3

Note that redis commands are shown here in uppercase, but they are accepted in
a case insensitive manner.

The redis connection is very thin wrapper around the redis protocol.
It simply formats the command according the redis protocol and converts
the response into the appropriate Tcl format.

Note that all values are binary strings, so keys and values in utf-8
format will be stored and returned exactly.

Return values
~~~~~~~~~~~~~

Responses from redis contain type information. These types are handled as follows:

* integer - returns the integer result
* string - returns the string result
* array - returns a list of elements (where each element is a redis type)
* nil - returns the empty string
* status - returns the status as a string
* error - returns an error with the message as the value

Accessing type information
~~~~~~~~~~~~~~~~~~~~~~~~~~

Normally the type of the return value doesn't matter as Jim treats everything as a string,
however it can be useful to differentiate between the empty string and nil, or between a status
return and an error return. In order to support this, the '-type' option is allowed as the
first word of the subcommand. In this case, whenever a value is returned, a list of {value type}
is returned instead. This is true recursively, so an array will return both the type for the array
and each element will include a type. The types are identified as follows:

* integer - "int"
* string - "str"
* array - "array"
* nil - "nil"
* status - "status"
* error - "error"

The following example illustrates the use of types:

    . $r -type KEYS a*
    {{abc str}} array
    . $r -type SET def 3
    OK status
    . $r INCR def
    4 int
    . $r -type GET missing
    {} nil
	. $r -type KEYS
	{ERR wrong number of arguments for 'keys' command} error

The read subcommand
~~~~~~~~~~~~~~~~~~~

While most redis commands return an immediate response, SUBSRIBE and PSUBSCRIBE
return multiple results over time. These responses can be (synchronously)
read with the 'read' subcommand, typically in conjunction with readable.

For example

    . $r SUBSCRIBE chan
    subscribe chan 1
    . $r read
    message chan PONG

If no message is received, the read command will wait forever.

The message is returned as: message <channel> <text>

The 'read' subcommand is also used in non-blocking mode. See the section below for more details.

The readable subcommand
~~~~~~~~~~~~~~~~~~~~~~~

Like normal aio sockets, the readable subcommand is supported to invoke
the given script when the underlying socket is readable.

    $r SUBSCRIBE channel
    $r readable {
        puts [$r read]
    }
    # wait forever, reading messages from the channel
    vwait forever

To remove the callback, invoke with no arguments (this is different from aio readable).

    # Remove the callback
    $r readable

The close subcommand
~~~~~~~~~~~~~~~~~~~~

The 'close' command is supported to close the connection.
This command is equivalent to deleting the command with:

    rename $r ""

Async/Non-blocking support
~~~~~~~~~~~~~~~~~~~~~~~~~~

It is possible to connect to redis in non-blocking mode by using the '-async' flag. e.g.

  set r [redis -async [socket stream localhost:6379]]

Now commands will return immediately with an empty result and 'read' in a 'readable' should
be used to retrieve the result. As a simple example:

  $r readable {
      set result [$r read]
      if {$result ne ""} {
          puts $result
          incr next
      }
  }
  $r SET x 5
  vwait next
  $r INCR x
  vwait next

Note that if a large result is returned, 'read' may return an empty string, in
which case further calls to 'readable' are required to return the result.

In general the underlying socket should be put into non-blocking mode ($sock ndelay 1)
and a while loop should be used to read reponses until and empty result is returned.