It's not bad enough where I had to pull it from the old project that used it, but going forward the new ones used a vibecoded queueing system that was genuinely more reliable than Celery but consumed a lot of memory (RSS inflation). Have then shifted to rq and at least for now it seems to "just work". You're better off doing anything custom/complex (like dependencies, or progress updates across multiple tasks) directly yourself in Redis anyway; since half the time Celery's less-well-trodden inbuilt features don't work the way they should anyway.
How did you find your expectations and celery's actual semantics to be different? I'm trying to document well and it seems like I might have some implicit assumptions that I could make explicit, but I don't know what they are since they're already in my head and matching celery it seems.
If you answered no to each question, just `import Queue from queue`.
Things like provisioning, deploying, and eventually destroying cloud instances (VMs) on-demand when a user buys a specific service.
> Do you need to be able to recover from a reboot or crash with your queues intact?
Yes, I expect the queue to be durable.
> Is it a distributed system as opposed to a single machine?
Currently, everything runs on a single machine. But I expect it will eventually have to be split up. Although I do not expect it to be massively distributed or very complex.
> Do you have complex multi-step workflows?
Depends on what you mean by complex but Multi-step, yes.
In my world cache systems like memcached and redis are just that, a cache to put and get from. Possibly use some invalidation system like tagging.
What can you do with a cache system that is 'wierd'? What are people doing with caches other than just caching data?
Genuinely interested.
- Rate limits for API endpoints via the leaky bucket algorithm
- Feature flags and stats tracking
- Websocket pub/sub
- Background job queue
In general, lots of things that need to survive deploys (so they can't be in-memory in the app) and/or they need to be coordinated across multiple horizontally scaled servers and/or things that prefer to be in a data structure which is slightly awkward to stick in a database table.
At some point someone decided to gzip all writes into memcached, and our site looked really fun for a while.
That requires some weirdness
So does that mean you are tracking how many times data is being entered into redis, and rejecting it if the entry rate is too high?
Why would you not track this before, at the point of calculating the data to enter into redis, rather than querying redis to see how much data is entered in a given timeframe?
Again, genuinely curious as to the reason for architectural decisions.
This is fairly easy to do if your apps runs on a single server, but many companies run multiple servers and load balance requests among them. Those servers need some sort of coordination mechanism to keep track of the rate limits and their current state. Redis has dedicated instructions these days to do this, and in the old days there were plethora of libraries that use embedded Lua scripts to do the same thing.
I don't exactly remember how i implemented it, but it basically did a single call to redis to count the request for the IP and check the limits.
Another usecase where the more advanced data types & operations of redis are usefull, is for job queues, since you can atomically move a job from the 'queue' to the 'processing' list, thus preventing loosing jobs if the processor crashes after pulling it orso. But we do run all those on persisted redis stores, for safety :)
And if i would do it all again, i'd probably just use postgres for anything i want to keep when things crash. Redis just kinda lives between a 'real' database and a pure volatile kv-cache