3

I have the following REDIS SET:

127.0.0.1:6379[2]> hgetall available
 1) "00001"
 2) "unassigned"
 3) "00002"
 4) "unassigned"
 5) "00003"
 6) "unassigned"
 7) "00004"
 8) "unassigned"
 9) "00005"
10) "unassigned"
127.0.0.1:6379[2]>

I have the following python code that uses a pipeline to "move" accounts from the available list to a reserved list / set:

def reserve_mailboxes(lower, upper):
    try:
        assert(lower is not None)
        assert(upper is not None)
        if DEBUG == True:  print("reserve_mailboxes invoked with lower limit: " + str(lower) + ", upper limit: " + str(upper))
        for number in range(int(lower), int(upper) + 1):
            number = '{0:05d}'.format(number) #zero pad 
            r = redis.Redis(connection_pool=POOL)
            p = r.pipeline()
            p.hmset('reserved', {number:'reserved'})
            p.hdel('available', {number})
            response = p.execute()
            logging.info(response)

            if not response[1] == True:
                if DEBUG == True: logging.info(response)
        return True
    except Exception as e:
        logging.error(e)
        return False

If you take a look at my code where I create and execute the pipeline, the hdel command actually has a syntax error. it really should be:

            p.hdel('available', number)

However, when I run this code it goes ahead and adds 2 entries to "reserved" list ... but doesn't remove them from the available list. This is what my data looks like at this point:

127.0.0.1:6379[2]> hgetall reserved
1) "00003"
2) "reserved"
3) "00004"
4) "reserved"
127.0.0.1:6379[2]> hgetall available
 1) "00001"
 2) "unassigned"
 3) "00002"
 4) "unassigned"
 5) "00003"
 6) "unassigned"
 7) "00004"
 8) "unassigned"
 9) "00005"
10) "unassigned"

The log shows the following "response" / result from the two commands:

root - INFO - [True, 0]

If the hdel worked, it should return a 1 not 0.

btw. When I remove the typo the code properly removes from one list and adds to the other.

Questions

  1. I thought the pipeline was supposed to revert all commands if one of them fails. So in other words, since the hdel is returning 0, should it undo the hmset?
  2. Is there a more efficient way to do this? Move a record from one set to another?
dot
  • 14,928
  • 41
  • 110
  • 218

2 Answers2

2
  1. Regardless what you thought, a pipeline is just a way to batch operations w/o waiting for the replies. The failure of one or more operations in the pipeline does not prevent either rolls back or other operations in it.

  2. These aren't Sets, but Hashes. You can look into Lua scripting (see the EVAL command) to optimize the performance of your logic by running it within the Redis server.

MarcinKonowalczyk
  • 2,577
  • 4
  • 20
  • 26
Itamar Haber
  • 47,336
  • 7
  • 91
  • 117
1

You can wrap the pipelined commands with MULTI and EXEC to make them "atomic".

For example:

MULTI
INCR pipeline_counter
EXPIRE pipeline_counts 3600
EXEC

See the doc of EXEC command for more information.

updogliu
  • 6,066
  • 7
  • 37
  • 50