Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for async backend clients #60

Closed
laurentS opened this issue Jun 8, 2020 · 4 comments
Closed

Add support for async backend clients #60

laurentS opened this issue Jun 8, 2020 · 4 comments
Milestone

Comments

@laurentS
Copy link
Contributor

laurentS commented Jun 8, 2020

In order to make slowapi asyncio compatible, I would need to update the layers underneath to work asynchronously. I think the key part is getting limits to support asyncio.

Would you be interested in me having a go at it? I think it would be possible to either:

  • add a few async def methods on the strategies, something like RateLimiter.ahit() and RateLimiter.atest()
  • Create AsyncRateLimiter and subclasses.

And then add an async storage backend, starting with redis.

Otherwise, if you see no interest in having this in the same code base, I guess I could fork the library and do more or less the same, but I think it's probably more valuable to have everything together.

@alisaifee
Copy link
Owner

I'd be happy to add this.

I haven't had a lot of experience working with asyncio and haven't quite figured how to achieve this without duplicating most of the Storage implementations. Regarding the API my initial thoughts are to have a separate namespace for the rate limit strategies - limits.async.strategies & limits.async.storage and additionally a new helper method async_storage_from_string.

From some quick research the following client libraries seem like good candidates:

Do you have any opinions on these or know of any other options?

Lastly, this will invariably end up in v2.0 which will be where I'll drop python2.x support and remove some of the legacy stuff like support for gae memcached.

@laurentS
Copy link
Contributor Author

Unfortunately, my feeling is similar with regards to duplicating the code. I've looked at a few examples of other libraries that offer both sync/async implementations, and a lot of it looks like copy/paste of entire functions. I guess this is really only needed for the part of the code that actually triggers blocking calls to the backends. Init code and such might not need duplicating. and we might manage to factor out the logic into a shared method, and keep the actual call to the storage in separate places.

Regarding redis clients, I did have a quick look as well. I initially thought of aioredis but found an issue on django's channels repo talking about moving away from it because the authors seem to have more or less abandoned the project for a few months now. They seem to want to move towards aredis, so it might be smart to follow the crowd, as it'll bring a bunch of extra eyes on the code there, I suppose?

I also came across walrus which is actively maintained but is probably a bit too spread out in terms of functionality for this purpose.

I will try to create the async strategies and storage under a separate namespace as you suggest, and I guess we'll see if and how we can keep some of the code shared between the two sides. Dropping python2.7 will definitely help with that :)

laurentS added a commit to laurentS/limits that referenced this issue Jun 13, 2020
This addresses issue alisaifee#60, but is still WIP. Support for more
backends is still needed.
@FesonX
Copy link

FesonX commented Oct 13, 2021

Unfortunately, my feeling is similar with regards to duplicating the code. I've looked at a few examples of other libraries that offer both sync/async implementations, and a lot of it looks like copy/paste of entire functions. I guess this is really only needed for the part of the code that actually triggers blocking calls to the backends. Init code and such might not need duplicating. and we might manage to factor out the logic into a shared method, and keep the actual call to the storage in separate places.

Regarding redis clients, I did have a quick look as well. I initially thought of aioredis but found an issue on django's channels repo talking about moving away from it because the authors seem to have more or less abandoned the project for a few months now. They seem to want to move towards aredis, so it might be smart to follow the crowd, as it'll bring a bunch of extra eyes on the code there, I suppose?

I also came across walrus which is actively maintained but is probably a bit too spread out in terms of functionality for this purpose.

I will try to create the async strategies and storage under a separate namespace as you suggest, and I guess we'll see if and how we can keep some of the code shared between the two sides. Dropping python2.7 will definitely help with that :)

The aioredis alive again! Any plan to support aioredis as storage backends?
Migration to aioredis 2.0 #930

alisaifee pushed a commit that referenced this issue Nov 28, 2021
This addresses issue #60, but is still WIP. Support for more
backends is still needed.
alisaifee pushed a commit that referenced this issue Dec 14, 2021
This addresses issue #60, but is still WIP. Support for more
backends is still needed.
@alisaifee alisaifee added this to the 2.1 milestone Dec 15, 2021
alisaifee pushed a commit that referenced this issue Dec 16, 2021
This addresses issue #60, but is still WIP. Support for more
backends is still needed.
alisaifee pushed a commit that referenced this issue Dec 16, 2021
This addresses issue #60, but is still WIP. Support for more
backends is still needed.
alisaifee pushed a commit that referenced this issue Dec 16, 2021
This addresses issue #60, but is still WIP. Support for more
backends is still needed.
@alisaifee
Copy link
Owner

This is now available in a pre-release (2.1.0bN) and contains support for redis, memcached & mongodb.
The support is limited to python 3.7, 3.8 & 3.9 as both the redis & memcached dependencies are not installable / functional on python 3.10 yet.

I'll soon be making a 2.1.0 release which contains these features - but you can take them for a ride already by installing for example:

pip install limits[async-redis]==2.1.0b3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants