I have a Rails app and use Jobs/Sidekiq for certain long running tasks and calculations.
I want to renew my menu-navigation if all jobs are done, by invalidating the cache returning the navigation and recalculate the content for that cache again. So users are seeing actual results and wont have long rendering pages.
I don't use actionViews, I use Rails as an API
Example
- Users are able to add items, which are starting long running tasks after saving (resizing images, up/downloading media, converting stuff...)
- When all these jobs have finished, the cache should get invalidated and recalculated.
At the moment I invalidate the cache in each job, but that's not optimal, because these jobs are always running in some way with other items, so the cache will never be available.
I thought on a specific database field (ie: visible
) or db table, which is true
when all jobs are done and observe that state, and based on that state recalulate results.
Another thought is create a db table
which represents the calculated results, and acts as a cache for my navigation.
What is the "right" way to handle that within Rails?
Process of saving items:
- DatabaseItem
- saving! && disabled visibility
- Up/Downloading Stuff (job)
- Resizing images (job)
- convert media (job)
- enabling item
- invalidate cache
- recalculating stuff (job) (or first visit of page)
- saving! && disabled visibility
Example of my navigation Tree which is very deep (>20k entries):
- RootItem (10 items)
- ChildItem (3 items)
- SubItem (2 items)
- SubItem (1 item)
- ChildItem (4 items)
- SubItem (2 items)
- SubItem (2 items)
- ChildItem (3 items)
I tried to handle that most generic as possible. If you need more details please let me know.
I use Rails
, Postgres
, Memcached
, Dalli
, actionpack-action_caching
Simplified:
class ItemSavedJob
include Sidekiq::Job
sidekiq_options retry: 3
# It activates or deactivates items
def perform(id)
item = Item.find(id)
item.make_invisible!
item.start_long_running_job
item.images.each do |image|
ItemConvertJob.perform_async(image.id)
# HERE when the last convertion has finished,
# it should activate the item and invalidate the Navigation
end
CacheHelper.invalidate_navigation_cache!
end
end
class ImageConvertJob
include Sidekiq::Job
sidekiq_options retry: 3
def perform(id)
image = Image.find(id)
image.do_a_long_convertion
end
end