joe_coolish
joe_coolish

Reputation: 7259

StackExchange.Redis support for ZPOP?

I want to impliment ZPOP for my application using StackExchange.Redis. According to the Redis documentation in the WATCH section, ZPOP can be implemented with the following commands:

WATCH zset
element = ZRANGE zset 0 0
MULTI
ZREM zset element
EXEC

In StackExchange Redis, this would look something like:

var connection = GetMultiplexer();
var db = connection.GetDatabase();
var trans = db.CreateTransaction();

var elements = await trans.SortedSetRangeByScoreAsync(key, 0, 0);  // THIS WILL BLOCK INDEFINITELY
var element = elemenets.FirstOrDefault();
trans.SortedSetRemoveAsync(key, element);
await trans.ExecuteAsync();

My question is, how can you get and use results from within a transaction? How can I implement ZPOP?

Upvotes: 1

Views: 699

Answers (1)

thepirat000
thepirat000

Reputation: 13124

Consider using a LUA script for that. Redis guarantees that lua scripts are transactional, because when an eval script is running, nothing else can run concurrently. So you can use EVAL.

Here is an example of how can you do the ZPOP with a LUA script:

local val = redis.call('zrange', KEYS[1], 0, 0)
if val then redis.call('zremrangebyrank', KEYS[1], 0, 0) end
return val

Also a ZREVPOP is provided.

With StackExchange.Redis you can load and execute LUA scripts with IServer.ScriptLoad and IDatabase.ScriptEvaluate.

https://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Transactions.md

Note this is not blocking. and will not be a good idea to have blocking code within the ConnectionMultiplexer.

From Stackexchange.Redis documentation:

...the only redis features that StackExchange.Redis does not offer (and will not ever offer) are the "blocking pops" (BLPOP, BRPOP and BRPOPLPUSH) - because this would allow a single caller to stall the entire multiplexer

Upvotes: 2

Related Questions