Home > Back-end >  Best approach for a scheduled update use case - ruby on rails
Best approach for a scheduled update use case - ruby on rails

Time:10-04

I have an specific requirement to be implemented, and any thoughts on thet would be welcome

The requirement

A given Appointment model has the following structure:

Appointment {
  status, # 'scheduled' or 'done'
  happens_at # Datetime
}

The status attribute that must be changed from scheduled to done at the time given by the attribute happens_at

Possible solutions

Scheduling a Job

Using rails Active Job framework, as soon as the tuple is created, we can simply call a Job that will be responsible for setting the status as 'done'

class Appointment < ApplicationRecord
  # ...
  def after_create
    RefreshAppointmentStatusJob.set(wait_until: created_appointment[:happens_at])
      .perform_later(created_appointment[:id])
  end
end

apparent PROS:

  • Easy to implement on creation

apparent CONS:

  • Need to handle job rescheduling if Appointment.happens_at is updated
  • What happens if my queue gets corrupted? How to make sure any "lost" scheduling would be rescheduled?

Using cron job running every minute

Then there is this other possible solution, which is basically a cro job running every minute with an implementation like

class RefreshStatusService < ApplicationService
  def call
    Appointment.where('happens_at <= ?',  date).update_all(status: 'done')
  end
end

apparent PROS:

  • Decouples this feature from Appointment creation/update/delete
  • Any problem regarding the queue/cron execution should not interfeer on database consistance after it is fixed (I mean, as soon as the query is run, any outdated status is going to be corretly updated)

apparent CONS:

  • Seems "dumb" to run this routine literally every minute, while probably most of thos runs are not updating anything
  • Every update will not actually happen on the correct happens_at, if it considers the seconds. It means we can have at most ~60 seconds of outdated data, which might be acceptable or not, deppending on the application

Best approach?

I've already implemented both solutions to similar problems, but every time I have to do it again I keep wondering which is the prefered solution. Any thoughts or opinions on thet would be very nice!

Note: I've used Ruby on Rails as example because it has built-in support for queues, but the problem itself would be faced on any other web framework

CodePudding user response:

I have used a third approach... based on the notion that, although status needs to be done after the happens_at date has passed, it really doesn't have to change at that moment, but it must be correctly set the next time anyone queries the object. So use an after_initialize callback, which will update the value of status whenever the object is fetched from the db, if the happens_at is in the past.

class Appointment < ApplicationRecord
  after_initialize :set_status

  def set_status
    update(status: 'done') if happens_at.past?
  end
end

CodePudding user response:

and here's yet another approach! Rename the status field to, say, raw_status and then add a status method:

class Appointment < ApplicationRecord
  def status
    return 'done' if happens_at.past?
    raw_status
  end
end
  • Related