Title: | R Bindings to 'hiredis' |
---|---|
Description: | A 'hiredis' wrapper that includes support for transactions, pipelining, blocking subscription, serialisation of all keys and values, 'Redis' error handling with R errors. Includes an automatically generated 'R6' interface to the full 'hiredis' API. Generated functions are faithful to the 'hiredis' documentation while attempting to match R's argument semantics. Serialisation must be explicitly done by the user, but both binary and text-mode serialisation is supported. |
Authors: | Rich FitzJohn [aut, cre] |
Maintainer: | Rich FitzJohn <[email protected]> |
License: | GPL-2 |
Version: | 1.1.4 |
Built: | 2024-11-27 06:11:30 UTC |
Source: | https://github.com/richfitz/redux |
Convert a Redis hash to a character vector or list. This tries to bridge the gap between the way Redis returns hashes and the way that they are nice to work with in R, but keeping all conversions very explicit.
from_redis_hash( con, key, fields = NULL, f = as.character, missing = NA_character_ )
from_redis_hash( con, key, fields = NULL, f = as.character, missing = NA_character_ )
con |
A Redis connection object |
key |
key of the hash |
fields |
Optional vector of fields (if absent, all fields are
retrieved via |
f |
Function to apply to the |
missing |
What to substitute into the returned vector for
missing elements. By default an NA will be added. A
|
if (redux::redis_available()) { # Using a random key so we don't overwrite anything in your database: key <- paste0("redux::", paste(sample(letters, 15), collapse = "")) r <- redux::hiredis() r$HSET(key, "a", "apple") r$HSET(key, "b", "banana") r$HSET(key, "c", "carrot") # Now we have a hash with three elements: r$HGETALL(key) # Ew, that's not very nice. This is nicer: redux::from_redis_hash(r, key) # If one of the elements was not a string, then that would not # have worked, but you can always leave as a list: redux::from_redis_hash(r, key, f = identity) # To get just some elements: redux::from_redis_hash(r, key, c("a", "c")) # And if some are not present: redux::from_redis_hash(r, key, c("a", "x")) redux::from_redis_hash(r, key, c("a", "z"), missing = "zebra") r$DEL(key) }
if (redux::redis_available()) { # Using a random key so we don't overwrite anything in your database: key <- paste0("redux::", paste(sample(letters, 15), collapse = "")) r <- redux::hiredis() r$HSET(key, "a", "apple") r$HSET(key, "b", "banana") r$HSET(key, "c", "carrot") # Now we have a hash with three elements: r$HGETALL(key) # Ew, that's not very nice. This is nicer: redux::from_redis_hash(r, key) # If one of the elements was not a string, then that would not # have worked, but you can always leave as a list: redux::from_redis_hash(r, key, f = identity) # To get just some elements: redux::from_redis_hash(r, key, c("a", "c")) # And if some are not present: redux::from_redis_hash(r, key, c("a", "x")) redux::from_redis_hash(r, key, c("a", "z"), missing = "zebra") r$DEL(key) }
Create an interface to Redis, with a generated interface to all Redis commands.
hiredis(..., version = NULL) redis_available(...)
hiredis(..., version = NULL) redis_available(...)
... |
Named configuration options passed to
|
version |
Version of the interface to generate. If given as
a string to numeric version, then only commands that exist up to
that version will be included. If given as |
There is no need to explicitly close the redis connection. It will be closed automatically when the connection goes out of scope and is garbage collected.
Some commands will block. This includes BRPOP
(and other
list commands beginning with B
). Once these commands have
been started, they cannot be interrupted by Ctrl-C from an R
session. This is because the redux
package hands over
control to a blocking function in the hiredis
(C) library,
and this cannot use R's normal interrupt machinery. If you want
to block but retain the ability to interrupt then you will need to
wrap this in another call that blocks for a shorter period of
time:
found <- NULL con <- redux::hiredis() found <- NULL while (is.null(found)) { found <- con$BLPOP("key", 1) Sys.sleep(0.01) # needed for R to notice that interrupt has happened }
# Only run if a Redis server is running if (redux::redis_available()) { r <- redux::hiredis() r$PING() r$SET("foo", "bar") r$GET("foo") # There are lots of methods here: r }
# Only run if a Redis server is running if (redux::redis_available()) { r <- redux::hiredis() r$PING() r$SET("foo", "bar") r$GET("foo") # There are lots of methods here: r }
Serialise/deserialise an R object into a string. This is a very
thin wrapper around the existing R functions
serialize
and rawToChar
. This is
useful to encode arbitrary R objects as string to then save in
Redis (which expects a string).
object_to_string(obj) string_to_object(str) object_to_bin(obj, xdr = FALSE) bin_to_object(bin)
object_to_string(obj) string_to_object(str) object_to_bin(obj, xdr = FALSE) bin_to_object(bin)
obj |
An R object to convert into a string |
str |
A string to convert into an R object |
xdr |
Use the big-endian representation? Unlike,
|
bin |
A binary vector to convert back to an R object |
s <- object_to_string(1:10) s string_to_object(s) identical(string_to_object(s), 1:10)
s <- object_to_string(1:10) s string_to_object(s) identical(string_to_object(s), 1:10)
Parse a Redis URL
parse_redis_url(url)
parse_redis_url(url)
url |
A URL to parse |
Primarily used for pipelining, the redis
object produces
commands the same way that the main redis_api
objects do. If passed in as arguments to the pipeline
method (where supported) these commands will then be pipelined.
See the redux
package for an example.
redis
redis
An object of class redis_commands
of length 199.
# This object creates commands in the format expected by the # lower-level redis connection object: redis$PING() # For example to send two PING commands in a single transmission: if (redux::redis_available()) { r <- redux::hiredis() r$pipeline( redux::redis$PING(), redux::redis$PING()) }
# This object creates commands in the format expected by the # lower-level redis connection object: redis$PING() # For example to send two PING commands in a single transmission: if (redux::redis_available()) { r <- redux::hiredis() r$pipeline( redux::redis$PING(), redux::redis$PING()) }
Create a Redis API object. This function is designed to be used from other packages, and not designed to be used directly by users.
redis_api(x, version = NULL)
redis_api(x, version = NULL)
x |
An object that defines at least the function
|
version |
Version of the Redis API to generate. If given as
a numeric version (or something that can be coerced into one.
If given as |
Create a set of valid Redis configuration options.
redis_config(..., config = list(...))
redis_config(..., config = list(...))
... |
See Details |
config |
A list of options, to use in place of |
Valid arguments here are:
url
The URL for the Redis server. See examples.
(default: Look up environment variable REDIS_URL
or
NULL
).
host
The hostname of the Redis server. (default:
127.0.0.1
).
port
The port of the Redis server. (default: 6379).
path
The path for a Unix socket if connecting that way.
password
The Redis password (for use with
AUTH
). This will be stored in plain text as part of
the Redis object. (default: NULL
).
db
The Redis database number to use (for use with
SELECT
. Do not use in a redis clustering context.
(default: NULL
; i.e., don't switch).
timeout
The maximum number of milliseconds to wait for the
connection to be established. (default: NULL
; i.e. wait forever).
The way that configuration options are resolved follows the design for redis-rb very closely.
First, look up (and parse if found) the REDIS_URL
environment variable and override defaults with that.
Any arguments given (host
, port
,
password
, db
) override values inferred from the url
or defaults.
If path
is given, that overrides the
host
/port
settings and a socket connection will be
used.
# default config: redis_config() # set values redis_config(host = "myhost") # url settings: redis_config(url = "redis://:p4ssw0rd@myhost:32000/2") # override url settings: redis_config(url = "redis://myhost:32000", port = 31000) redis_config(url = "redis://myhost:32000", path = "/tmp/redis.conf")
# default config: redis_config() # set values redis_config(host = "myhost") # url settings: redis_config(url = "redis://:p4ssw0rd@myhost:32000/2") # override url settings: redis_config(url = "redis://myhost:32000", port = 31000) redis_config(url = "redis://myhost:32000", path = "/tmp/redis.conf")
Create a Redis connection. This function is designed to be used
in other packages, and not directly by end-users. However, it is
possible and safe to use. See the hiredis
package
for the user friendly interface.
redis_connection(config = redis_config())
redis_connection(config = redis_config())
config |
Configuration parameters as generated by
|
This function creates a list of functions, appropriately bound to a pointer to a Redis connection. This is designed for package authors to use so without having to ever deal with the actual pointer itself (which cannot be directly manipulated from R anyway).
The returned list has elements, all of which are functions:
config()
The configuration information
reconnect()
Attempt reconnection of a connection that has been closed, through serialisation/deserialisation or through loss of internet connection.
Run a Redis command. The format of this command will be documented elsewhere.
Run a pipeline of Redis commands.
Subscribe to a
channel or pattern specifying channels. Here, channel
must
be a character vector, pattern
a logical indicating if
channel
should be interpreted as a pattern, callback
is a function to apply to each received message, returning
TRUE
when subscription should stop, and envir
is the
environment in which to evaluate callback
. See below.
The callback function must take a single argument; this will be
the received message with named elements type
(which will
be message), channel
(the name of the channel) and
value
(the message contents). If pattern
was
TRUE
, then an additional element pattern
will be
present (see the Redis docs). The callback must return
TRUE
or FALSE
; this indicates if the client should
continue quit (i.e., TRUE
means return control to R,
FALSE
means keep going).
Because the subscribe
function is blocking and returns
nothing, so all data collection needs to happen as a side-effect
of the callback function.
There is currently no way of interrupting the client while it is waiting for a message.
Parse and return Redis INFO
data.
redis_info(con) parse_info(x) redis_version(con)
redis_info(con) parse_info(x) redis_version(con)
con |
A Redis connection |
x |
character string |
if (redux::redis_available()) { r <- redux::hiredis() # Redis server version: redux::redis_version(r) # This is a 'numeric_version' object so you can compute with it # if you need to check for minimum versions redux::redis_version(r) >= numeric_version("2.1.1") # Extensive information is given back by the server: redux::redis_info(r) # Which is just: redux::parse_info(r$INFO()) }
if (redux::redis_available()) { r <- redux::hiredis() # Redis server version: redux::redis_version(r) # This is a 'numeric_version' object so you can compute with it # if you need to check for minimum versions redux::redis_version(r) >= numeric_version("2.1.1") # Extensive information is given back by the server: redux::redis_info(r) # Which is just: redux::parse_info(r$INFO()) }
Helper to evaluate a Redis MULTI
statement. If an error
occurs then, DISCARD
is called and the transaction is
cancelled. Otherwise EXEC
is called and the transaction is
processed.
redis_multi(con, expr)
redis_multi(con, expr)
con |
A Redis connection object |
expr |
An expression to evaluate |
Load Lua scripts into Redis, providing a convenience function to
call them with. Using this function means that scripts will be
available to use via EVALSHA
, and will be preloaded on the
Redis server. Scripts are then accessed by name rather
than by content or SHA. See the vignette for details and an
example.
redis_scripts(con, ..., scripts = list(...))
redis_scripts(con, ..., scripts = list(...))
con |
A Redis connection |
... |
A number of scripts |
scripts |
Alternatively, a list of scripts |
Get time from Redis and format as a string.
redis_time(con) format_redis_time(x) redis_time_to_r(x)
redis_time(con) format_redis_time(x) redis_time_to_r(x)
con |
A Redis connection object |
x |
a list as returned by |
if (redux::redis_available()) { r <- redux::hiredis() # The output of Redis' TIME command is not the *most* useful # thing in the world: r$TIME() # We can get a slightly nicer representation like so: redux::redis_time(r) # And from that convert to an actual R time: redux::redis_time_to_r(redux::redis_time(r)) }
if (redux::redis_available()) { r <- redux::hiredis() # The output of Redis' TIME command is not the *most* useful # thing in the world: r$TIME() # We can get a slightly nicer representation like so: redux::redis_time(r) # And from that convert to an actual R time: redux::redis_time_to_r(redux::redis_time(r)) }
Support for iterating with SCAN
. Note that this will
generalise soon to support collecting output, SSCAN
and
other variants, etc.
scan_apply( con, callback, pattern = NULL, ..., count = NULL, type = "SCAN", key = NULL ) scan_del(con, pattern, count = NULL, type = "SCAN", key = NULL) scan_find(con, pattern, count = NULL, type = "SCAN", key = NULL)
scan_apply( con, callback, pattern = NULL, ..., count = NULL, type = "SCAN", key = NULL ) scan_del(con, pattern, count = NULL, type = "SCAN", key = NULL) scan_find(con, pattern, count = NULL, type = "SCAN", key = NULL)
con |
A |
callback |
Function that takes a character vector of keys and
does something useful to it. |
pattern |
Optional pattern to use. |
... |
additional arguments passed through to |
count |
Optional step size (default is Redis' default which is 10) |
type |
Type of SCAN to run. Options are |
key |
Key to use when running a hash, set or sorted set scan. |
The functions scan_del
and scan_find
are example
functions that delete and find all keys corresponding to a given
pattern.
Redis object cache driver
storr_redis_api( prefix, con, hash_algorithm = NULL, default_namespace = "objects" ) driver_redis_api(prefix, con, hash_algorithm = NULL)
storr_redis_api( prefix, con, hash_algorithm = NULL, default_namespace = "objects" ) driver_redis_api(prefix, con, hash_algorithm = NULL)
prefix |
Prefix for keys. We'll generate a number of keys that start with this string. Probably terminating the string with a punctuation character (e.g., ":") will make created strings nicer to deal with. |
con |
A |
hash_algorithm |
Name of the hash algorithm to use. Possible
values are "md5", "sha1", and others supported by
|
default_namespace |
Default namespace (see |
Rich FitzJohn