Question

I'm currently using Andy McCurdy's redis.py module to interact with Redis from Django

I offload certain tasks into the background using Celery.

Here is one of my tasks:

import redis
pool = redis.ConnectionPool(host='XX.XXX.XXX.X', port=6379, db=0, password='password')
r_server = redis.Redis(connection_pool=pool)
pipe = r_server.pipeline()

# The number of seconds for two months
seconds = 5356800

@shared_task
def Activity(userID, object_id, timestamp):
        timestamp = int(timestamp)
        # Create Individual activity for each.
        activity_key = 'invite:activity:%s:%s' % (userID, timestamp)
        mapping = dict(
            user_id = userID,
            object_id = object_id)
        pipe.hmset(activity_key, mapping).expire(activity_key, seconds).execute()

Whenever this task is invoked, I get the following error:

AttributeError: 'bool' object has no attribute 'expire'

What could possibly be causing this?

I later did a test in a python console to see if there was something wrong with my syntax, but everything worked just as I had planned. So what could possibly be causing this error?

UPDATE

I think the expire is evaluating the result of hmset(activity_key, mapping). This is weird! expire is a method for pipe.

SECOND UPDATE

I found a work around for the time being. It seems this only occurs within Celery. Native Django views and the python console don't exhibit this behavior. It seems to evaluate the result of the expression before it. If any of you come across this problem, here is a work around.

pipe.hmset(activity_key, mapping)
pipe.lpush('mylist', 1)
pipe.expire('mylist', 300)
pipe.execute()

This should work and not give you any issues. Happy Coding!

Was it helpful?

Solution

pipe.hmset() does not return the pipeline; you cannot chain the calls here. Instead, a boolean is returned (probably indicating if the hmset() call succeeded).

Call the .expire() and .execute() methods separately:

pipe.hmset(activity_key, mapping)
pipe.expire(activity_key, seconds)
pipe.execute()

I suspect you need to create a pipeline within the Celery task instead of re-using a global here. Move the pipe = r_server.pipeline() to within the activity.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top