Files in directory assets/retcl0 in any check-in
- examples
- LICENSE
- pkgIndex.tcl
- README.md
- retcl.tcl
The retcl module is an event-driven, object-oriented,
Redis client library for the
Tcl programming language. The library
exposes a single retcl
class, conveniently packaged as a sourceable
Tcl module.
Instances of this class represent connections to a
Redis server and are used to send requests in the
form of native Redis commands and retrieve
responses.
Other than a few book-keeping methods, retcl
instances transparently
handle Redis commands as first-class methods. As an
example, r SET K Hello
can be used to set the value of the key K to
the string Hello. This is achieved by proxying all unknown methods to
the Redis server by concatenating all arguments,
effectively making retcl
instances completely decoupled from any
version of Redis. This has several advantages:
A
retcl
instance does not need to know about the semantics of a particular Redis command. This includes syntax checks, context verification and arguments validation, which are offloaded to the Redis server. As a consequence, the code base remains clean and small.New commands introduced by a server upgrade are immediately available to a live application.
package require retcl retcl create r r SET key val r -sync GET key ;# val
Construction
set r [retcl new ?host port? ?option ...?]
set r [retcl new ?-noconnect? ?option ...?]
retcl create r ?host port? ?option ...?
retcl create r ?-noconnect? ?option ...?
Create an instance r of retcl
. If no host
or port
is
specified, the client automatically connects to localhost on port 6379.
If -noconnect
is specified, the client is created in disconnected
mode. Each additional option
is a simple string or a list representing
the invocation of a configuration method. Here are some examples.
retcl create r localhost 6973 -async {+tls -cafile /path/to/ca.crt}
retcl create r -keepCache
retcl create r -noconnect -keepCache +async
Connection / disconnection
$r connect ?host? ?port?
$r disconnect
$r connected
The connect
method can be used to connect to a different host and
port. It is an error to call this method on an already connected client.
The disconnect
method can be called no matter the connection status;
it disconnects the client from the current host, if any. The connected
method can be used to query the current connection status. It returns a
true result if the client is connected and a false result otherwise.
Interaction with Redis
set rid1 [$r SET key val] ;# rid stands for result id
$r result $rid1 ;# OK
set rid2 [$r GET key]
$r result $rid2 ;# val
$r resultType $rid1 ;# SimpleString
$r resultType $rid2 ;# BulkString
$r -sync GET key ;# val
proc mycb {id type body} {
puts " id: $id"
puts "type: $type"
puts "body: $body"
}
$r -cb mycb GET key ;# returns immediately and arrange for mycb to be invoked
;# with {rds:1 BulkString val} when the result arrives
As shown in the examples above, the interaction with
Redis is very straightforwards. Any methods not
directly understood by the retcl
class are forwarded to the
Redis server, along with any additional arguments
provided. The result is a small string representing a result id. Each
call to Redis produces a new result id, which can
then be queried to inspect its status, type, and value.
By using the -sync
switch, it is possible to have
Redis commands block and only return as soon as the
result is available. In this case, the return value is the value
returned by Redis.
By using the -cb
switch, it is possible to arrange for a callback
procedure to be called whenever the result is ready. In this case, the
command returns immediately.
Configuration
By default, retcl
objects operate in asynchronous mode: they return
immediately and produce a result id (rid) that can be inspected later
on. The methods -async
, +async
and ?async
can be used to disable,
enbale, and query this setting. When the asynchronous behaviour is off,
methods wait and return the values returned by Redis
instead of a result id.
A cache of all results is kept by default. This allows to query
previously returned results. The -keepcache
, +keepcache
, and
?keepcache
methods can be used to disable, enable, and query this
setting. When the results cache is disabled, results are removed from
the cache as soon as they are retrieved by the client.
Error handling
A custom error handler can be setup with the errorHandler
method. The
argument is a command prefix that gets expanded and additioned with an
error message string. Passing an empty command prefix resets the error
handler to the default error
proc.
Pipelining
A pipeline can be built with the pipeline
method. The argument is a
script which gets evaluated in the context of the caller. Commands to
the Redis server are held for the duration of the
script and released as a bulk when the script ends.
Publish / subscribe
Publish / subscribe callbacks for specific items can be specified with
the callback
method. The item
argument is a pattern or channel as in
PSUBSCRIBE and SUBSCRIBE. The callback
argument is a command prefix.
Whenever a message arrives on the specific channel, the command prefix
is called by appending the type of the message, the pattern that was
subscribed to, the actual channel, and the payload.
TLS
The connection to the Redis server is unencrypted by
default. If the TclTLS
extension is available, the +tls
method can be used to enable TLS. The
method takes an optional list of arguments that are passed as-is to the
[tls::socket]
command. In the default configuration,
Redis requires a valid client certificate on
connection, which requires specifying a few parameters, e.g.,
r +tls -cafile /etc/redis/ca.crt -certfile /etc/redis/redis.crt -keyfile /etc/redis/redis.key
.
The -tls
and ?tls
methods can be used to disable and query TLS mode.
The ping-pong example can be
run in TLS mode via tclsh ping-pong.tcl --tls
.
Encoding
As per the Redis Serialization Protocol (RESP), commands are sent over the wire as arrays of bulk strings. Bulk strings contain binary data, so all strings need to be converted to byte streams with values in the range 0-255. Unicode strings need to be encoded in utf-8.