> but the state is not consistent in a
but the state is not consistent in a concurrent requestsCan you give more details what exactly are you doing here? A Durable Object runs a single request at a specific point in time, and only schedules a different request when you do async IO in your logic. So as long as you are only doing synchronous operations, or one of the
transaction()
methods on the storage API that allow you to use async actions, your storage access should be consistent.10 Replies
I'm building a rate limiting worker that keeps a counter and reset it after a specified interval.
I'm using DO state for maintaining the counter data and
alarm
to persist the state every 1s to storageOK, and what's the inconsistency you observed?
What storage operations are you doing, can you share that snippet of code to see exactly where there might be something problematic?
Sure, here is my DO object
The
setAlarm()
needs the timestamp epoch millis when to run your handler, not the duration from "now". See https://developers.cloudflare.com/durable-objects/api/alarms/#setalarm You are always setting the alarm 1s after UNIX epoch (1970).
Also, keep in mind that since you only store within the alarm handler, if your DO crashes for any reason before the alarm runs, the in memory state is lost. So, depending on your rate limit accuracy requirements, you should adjust the alarm frequency as necessary.oh great! Thank you for the feedback. I will update the
alarm
Also, you need to make sure that your
this.data
is initialized before trying to call updateCount()
since if there is nothing stored yet, it will be undefined
and you will try to increment the count, hence failing.would it help if I persist data on every
this.updateCount
invocation?
Also, you need to make sure that your this.data is initialized before trying to call updateCount()oh interesting, what's the right way to ensure that?
Up to your needs. You will always have consistent state but lead to more writes, so it depends on your needs.
check that
this.data
is valid before trying to increase the count and initialize it if not.
Or guarantee in the caller code that you never call updateCount()
before setRateLimit()
has been called, and persisted at least once.
BTW, calling setRateLimit()
multiple times means you reset the counter each time.
I don't know how you use the above DO so check your business logic needs.sounds good. let me work on the feedback and report back. Thank you
Not sure if it’s useful for your use case or if you have a need to use a DO, but Workers have a Rate Limiting API that would save you a lot of work if there’s nothing out of the ordinary that you need: https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/
Cloudflare Docs
Rate Limiting · Cloudflare Workers docs
Define rate limits and interact with them directly from your Cloudflare Worker