Name
====

Retcl - Redis client library for Tcl

Synopsis
--------

    package require retcl
    retcl create ?objectName? ?-noconnect? ?host? ?port?
    set r [retcl new ?-noconnect? ?host? ?port?]
    $r connect ?host? ?port?
    $r disconnect
    $r connected
    $r ?-sync? ?-cb? redisCmd ?redisArg ...?
    $r result ?async? commandId
    $r resultReady commandId
    $r resultType commandId
    $r allResults
    $r clearResult ?commandId?
    $r +async
    $r -async
    $r ?async
    $r +keepCache
    $r -keepCache
    $r ?keepCache
    $r errorHandler ?cmdPrefix?
    $r pipeline script
    $r callback item ?callback?

Description
-----------

The retcl module is an event-driven, object-oriented,
[Redis](https://redis.io) client library for the
[Tcl](https://www.tcl-lang.org/) programming language. The library
exposes a single `retcl` class in a Tcl package.
Instances of this class represent connections to a
[Redis](https://redis.io) server and are used to send requests in the
form of native [Redis](https://redis.io) commands and retrieve
responses.

Other than a few book-keeping methods, `retcl` instances transparently
handle [Redis](https://redis.io) 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](https://redis.io) 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](https://redis.io) command. This includes syntax
    checks, context verification and arguments validation, which are
    offloaded to the [Redis](https://redis.io) 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.

Construction
------------

    set r [retcl new ?-noconnect? ?host? ?port?]
    retcl create r ?-noconnect? ?host? ?port?

Create an instance *r* of `retcl`. By default, the client automatically
connects to localhost on port 6379. If `-noconnect` is specified, the
client is created in disconnected mode.

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](https://redis.io) is very straightforwards. Any methods not
directly understood by the `retcl` class are forwarded to the
[Redis](https://redis.io) server, along with any additional arguments
provided. The result is a small string representing a result id. Each
call to [Redis](https://redis.io) 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](https://redis.io) commands block and only return as soon as the
result is available. In this case, the return value is the value
returned by [Redis](https://redis.io).

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. The asynchronous behaviour is off,
methods wait and return the values returned by [Redis](https://redis.io)
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](https://redis.io) 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.

Resources
---------

[Project page](https://gahr.github.io/retcl)

[Repository](https://github.com/gahr/retcl)

Copying
-------

Copyright (C) 2014-2018 Pietro Cerutti

Free use of this software is granted under the terms
of the BSD-2-Clause License.
