Skip to content

AlphaHydrae/multi_redis

Repository files navigation

Multi Redis

Pattern to execute separate redis-rb operations in the same command pipeline or multi/exec.

Gem Version Dependency Status Build Status Coverage Status

Installation

Put this in your Gemfile:

gem 'multi_redis', '~> 0.3.0'

Then run bundle install.

Usage

Assume you have two separate methods that call redis:

$redis = Redis.new
$redis.set 'key1', 'foo'
$redis.set 'key2', 'bar'

class MyRedisClass

  def do_stuff
    $redis.get 'key1'
  end

  def do_other_stuff
    $redis.get 'key2'
  end
end

o = MyRedisClass.new
o.do_stuff         #=> "foo"
o.do_other_stuff   #=> "bar"

This works, but the redis client executes two separate requests to the server, and waits for the result of the first one to start the second one:

Request 1:
- GET key1

Request 2:
- GET key2

The redis-rb gem allows you to run both calls in the same command pipeline:

results = $redis.pipelined do
  $redis.get 'key1'
  $redis.get 'key2'
end

results[0]   #=> "foo"
results[1]   #=> "bar"

There is only one request now, but the two $redis.get calls are no longer in separate methods. To keep them separate, you would have to write your methods so that they could be called in a pipeline. But in a pipeline redis calls return futures, not values, because the calls have not been executed yet.

Multi Redis provides a pattern to more easily handle these futures. It allows you to structure your code so that your separate redis calls may be executed together in one request when needed.

$redis = Redis.new
$redis.set 'key1', 'foo'
$redis.set 'key2', 'bar'

MultiRedis.redis = $redis   # Give Multi Redis a redis-rb client to use.

# Create a redis operation, i.e. an operation that performs redis calls, equivalent to the first method.
do_stuff = MultiRedis::Operation.new do
  pipelined{ |mr| mr.redis.get 'key1' }   # Run your redis command in a pipelined block. It will return a future.
  run{ |mr| mr.last_replies[0] }        # Access the result in a run block. The future has been resolved.
end

# Executing the operation will run all blocks in order and return the result of the last block.
do_stuff.execute   #=> "foo"

# Create another redis operation for the other method.
do_other_stuff = MultiRedis::Operation.new do
  pipelined{ |mr| mr.redis.get 'key2' }
  run{ |mr| mr.last_replies[0] }
end

do_other_stuff.execute   #=> "bar"

The two operations can still be executed separately like before, but they can also be combined through Multi Redis:

MultiRedis.execute do_stuff, do_other_stuff

Both redis calls get grouped into the same command pipeline:

One request:
- GET foo
- GET bar

The array of results is returned by the execute call:

MultiRedis.execute do_stuff, do_other_stuff   #=> [ "foo", "bar" ]

Meta

  • Author: Simon Oulevay (Alpha Hydrae)
  • License: MIT (see LICENSE.txt)

About

Pattern to execute separate redis-rb operations in the same command pipeline or multi/exec.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages