I created a small class to perform basic operations with redis, using aioredis.
class RedisService:
def __init__(self, r_url) -> str:
self.redis = r_url
async def create_connection(self):
return await aioredis.create_redis(self.redis)
async def _get(self, key) -> str:
try:
return await self.create_connection().get(key, encoding='utf-8')
finally:
await self._close()
async def _set(self, key, value) -> None:
await self.create_connection().set(key, value)
await self._close()
async def _close(self) -> None:
self.create_connection().close()
await self._redis.wait_closed()
And a test handler to call the write/read operation for redis
@router.post('/perform')
async def index():
key = 'test'
value = 'test'
value = await RedisService(r_url)._set(key, value)
return {'result': value}
But get error
await self.create_connection.set(key, value)
AttributeError: ''coroutine'' object has no attribute 'set'
I guess the problem could be that the asynchronous code has to be run through an event loop
asyncio.run(some coroutine)
But I can’t understand how I can build this logic into my code
2
Answers
event_loop provided by uvicorn when a fastapi app is launched can take care of calling redis get/set value in an asynchronous fashion.
refer -> https://fastapi.tiangolo.com/tutorial/first-steps/
below code snippet available at "https://github.com/tiangolo/fastapi/issues/1694" is altered to fit the ask from question.
moving the create connection result inside the object state helps taking care of asynchronous resolution of network call.
when path "/" is queried object’s state which holds the connection will be used to
set the result in an asynchronous fashion to redis.
Your problem is how you use
create_connection
. You have to call it and await what it returns.You’ll then need to await
set
andget
as well. As a one-liner this would get messy.To help clean this up, you should split the awaits into separate statements.
Creating a new connection each time you need to perform an operation can be expensive. I’d recommend changing
create_connection
in one or two ways.Either have it attach the connection to your instance
You can call this after you instantiate an instance of
RedisService
and then useOr you can switch to using a connection pool.