grempe / ex_rated

ExRated, the Elixir OTP GenServer with the naughty name that allows you to rate-limit calls to any service that requires it.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Open to a Pluggable Storage adapter refactor?

russmatney opened this issue · comments

Hey there!

Are you open to a PR that pulls the datastore (ets) usage into an adapter style? We're looking to implement rate limiting, but would like something that works across nodes in our cluster.

We'd probably pull the ets implementation into an included adapter, and write another adapter for something like redis as a separate repo.

Hmmm. I guess I am open to it but from a performance perspective Redis would likely be at least an order of magnitude slower for each check (current code is less the 5 microseconds, not milliseconds, each) and there would be a lot of overhead to handle failure scenarios. If you are running a single redis instance you now have a less performant, less reliable, SPOF. Don't get me wrong, I love Redis, but I'm not clear on the benefits in this case. ex_rated is a supervised process in the BEAM, Redis is not and has its own complex failure scenarios whether run as a single instance or in a cluster.

If you want to take a crack at a refactor in a fork that's cool. I guess I would have to see the final code to see if its something I want to take on and merge (this was written as a learning experience and I am not currently actively using Elixir or this rate limiter so I want to keep my maintenance efforts near zero at the moment). If not, of course you are free, and encouraged to hard fork this project and publish it independently.

Pull request has to be well tested and there should be no breaking API changes required for using the default case of ETS. Running the tests should not require a running instance of Redis optimally.

Cheers.

Thanks for the thoughts, and I appreciate the performance and failure-handling insights. I definitely agree ETS is a more optimized solution, and should always beat a networked store when running on one machine.

Unless it's a misunderstanding on my part, I don't believe ETS is supported across multiple nodes in a distributed Elixir/BEAM application. A shared datastore would provide a way to handle this. (Redis is just an example, an adapter storage style would make it easy to play with a few options). Is this a misunderstanding on my part? From some preliminary reading it looks like DETS or Mnesia are erlang/elixir ways to solve this problem.

A PR is in the works – very much appreciate you taking the time.

I have not tried this, but can't you run the process on a single node and send messages to it from distributed connected nodes? If so, would this not be more reliable/faster than calling out to an external Redis instance?

http://elixir-lang.org/getting-started/mix-otp/distributed-tasks-and-configuration.html

That is a potential option - the overhead would shift to configuring the storage on that node to persist properly across rolling updates (overhead that would arguably go into whatever storage layer, i.e. redis).

From my perspective, ex_rated shouldn't dictate an architectural decision if it can be deferred, so I'd still opt for an adapter-driven storage layer. That should achieve the same performance via the default ETS adapter, and allow anyone to write their own adapter for whatever their use-case.

We should have a PR ready this week. No worries if it's not something you want to merge in – either way, your input would be appreciated.

Any progress on this?

I also think it's pretty essential for these rate-limiters to work in a multi-node situation.

@ShaneKilkelly we ended up moving toward writing our own, so this won't see any progress on my end.