[−][src]Module actix_ratelimit::stores
Type used to store ratelimiter data associated with a client.
A store actor which acts on a store and is
responsible for performiing all sorts of operations(set, get, delete, etc). It is Important to
note that there are multiple store actors acting on a single store. Therefore, while
implementing your store, is should be Send
+ Sync
.
When a new key is created, tokens are assigned to it based on the value of max_requests which are valid for an interval. Once time has elapsed equal to the interval, the key is removed from the store. Memory store uses deferred messages to the actor to accomplish this, whereas key expiry is used for redis.
Store actors are implemented as supervised actors, and if you implement your own store, it is recommended to implement it as a Supervised actor to achieve some level of fault tolerance.
Implementing a custom store:
use std::collections::HashMap; use std::time::Duration; use actix::prelude::*; use actix_ratelimit::{ActorMessage, ActorResponse}; use futures::future::{ok, err}; struct MyStore(HashMap<String, usize>); impl MyStore{ pub fn new() -> Self { let map: HashMap<String, usize> = HashMap::new(); Self(map) } } struct MyStoreActor { inner: HashMap<String, usize> } impl Actor for MyStoreActor{ type Context = Context<Self>; } impl Handler<ActorMessage> for MyStoreActor{ type Result = ActorResponse; fn handle(&mut self, msg: ActorMessage, ctx: &mut Self::Context) -> Self::Result { match msg { // Handle Set message ActorMessage::Set {key, value, expiry} => { self.inner.insert(key, value); ActorResponse::Set(Box::pin(ok(()))) }, // Handle Update message ActorMessage::Update {key, value} => { let mut new_val:usize; let val = self.inner.get_mut(&key).unwrap(); *val -= value; let new_val = *val; ActorResponse::Update(Box::pin(ok(new_val))) }, // Handle get message ActorMessage::Get(key) => { let val = *self.inner.get(&key).unwrap(); ActorResponse::Get(Box::pin(ok(Some(val)))) }, // Handle Expire message ActorMessage::Expire(key) => { // dummy value, you need to implement expiration strategy ActorResponse::Expire(Box::pin(ok(Duration::from_secs(10)))) }, // Handle Remove message ActorMessage::Remove(key) => { let val = self.inner.remove(&key).unwrap(); ActorResponse::Remove(Box::pin(ok(val))) }, } } }
Note
The above example is not thread-safe and does not implement key expiration! It's just for demonstration purposes.
Modules
memcached | Memcached store for rate limiting |
memory | In memory store for rate limiting |
redis | Redis store for rate limiting |