How would you implement metered access? So actor A...
# getting-started
h
How would you implement metered access? So actor A is only allowed to access Resource B 100 times a second for example. Would you have a
ConcurrentList<Pair<Long, String>>
and add the timestamp on each access and
removeAt(0)
for each item above a limit like 5000 entries. Then just count the amount of entries for
String
with
Long
higher than
now - 1000
? Or have an
ConcurrentHashMap<String, Int>
and substract 1 every 10ms and add 1 for each access? Both sound kind of slow.
c
A really simple way to implement it may be to use a
Semaphore(1000)
and just add a
delay(1000)
to each request to force it to take at least 1s. This way, if more requests are started, they are forced to wait until the previous ones are finished.
k
Consider using resilience4j.
h
I will definitely continue to check out resilience4j, thanks for pointing it out. I also really like to just use
Semaphore
, but the response is somewhat time critical. It's not stock market levels of urgent, but waiting a for more than 250ms is not an option. The meter is just to force the (b2b) customer to buy a higher access rate and flood protection, but the request itself should be fast. Maybe I can return early via a callback or something and have the semaphore blocking part linger for some ms to keep a certain rate per second/minute. Edit: Or I could just do a
tryAquire
and if it fails I return
TooManyRequest
and if I get the permit I immediately respond to the call, but let the thread linger for X ms.
Works perfectly, chef's kiss. Thank you.
c
I meant, put the
delay
at the end of the request, after you've answered to the client. This way, it doesn't slow down anything.
I'd recommend using a custom data class here, Pair makes this hard to read
h
The delay is at the end if you look into the pictures.
And yes, I will now build upon this poc with data classes and other changes. This was just to check if everything behaves as expected. There are other parts that also need change for it to become production ready.
👍 1
c
To be fair, if you're going to use the semaphore like this, you could just increment/decrement an AtomicInt
That's probably what Semaphore does anyway, but it has some additional logic to wait on the semaphore being open, which you don't need since you just give up on requests that are too frequent
h
I also explored that before you suggested the Semaphore, but it's nice that Semaphore gives me the tryAquire and release for free.
And it also fits nicely that I just pass null for rates that were not applied to prevent the second rating to distort the minute rating and vice versa. I bet that would also have worked with AtomicInt, but I really like it this way.