Have you ever seen a code like this using an Old Resque technology?
NOTE: Some details were removed to avoid making any references to a production code like this
# frozen_string_literal: true
class MySuperDuperNotificationsCount < Retryable
@queue = :integrations
class << self
def perform
# Validating if Notification exist
return unless msg_type.present?
# This job will check if doctors have the electronic prescriptions service Notifications and will send
# a notification per Doctor to each manager
doctors.each do |doctor|
send_managers_notification(doctor) unless notifications_empty?(doctor.prescription_notifications)
end
end
private
def msg_type
@msg_type ||= MessageType.find_by(group: 'electronic_prescriptions', name: 'doctor notifications count')
end
def doctors
# We need to reduce as much as possible the amount of records to iterate
# TODO: While this shortens the search there might be other things
# that we could add like last login time
@doctors ||= User.with_electronic_prescriptions_enabled
.enabled_users
.doctors
.where.not(prescription_notifications: nil)
end
def notifications_count(notifications)
MyApplicationNamespace::ElectronicPrescriptions::NotificationHelper.notifications_count(notifications)
end
def notifications_empty?(prescription_notifications)
# While the query (doctors) already checks for nil values,
# due to the way prescription_notifications is build, it can have values
# but that doesn't mean it has notifications
# Examples:
# "[]" No partnerships
# "[{:clinic_id=>1}, {:clinic_id=>2}]" Two partnerships but no notifications
# So we need to cover/validate that here
# This verify if any of the notification types has notifications
!MyApplicationNamespace::ElectronicPrescriptions::NotificationHelper.has_pending_notifications(
# At this point prescription_notifications is separated by partnerships
# So we need to count the total of notifications by type
notifications_count(prescription_notifications)
)
end
def send_managers_notification(doctor)
# As required, this will send a Notification to all managers telling them
# that a specific doctor has pending rcopia notifications
# 1 Notification per Doctor per manager
# TODO: Managers for Organization returns staff (including owners)
# So we need to call managers again (for Users) to scope to Managers only
doctor.organization.managers.managers.each do |manager|
# Here we check only for in app notifications settings,
# if user has the notification enabled we can send the notification,
# currently this doesn't care aout email settings as the email is not implemented
notification_enabled = manager.notification_settings.find_by(
notification_type_id: notification_type.id
)&.send_in_app
return unless notification_enabled
MyApplicationNamespace::Notifications::Manager.queue_notification(
user_id: manager.id,
notification_type_id: notification_type.id,
notifiable_type: doctor.class.to_s,
notifiable_id: doctor.id,
payload: notifications_count(doctor.prescription_notifications)
)
end
end
end
end
And you are running that code every 15 minutes?
What architecture you are following to avoid that?
Well, In this guide we are going to review how to become from that to turn into something great like this:
ServiceEnqueuerJob.enqueu(
'GoogleApis::AppointmentCalendarEventCreator',
'create_event_from',
appointment_id
)
or at least like this If you are still using Resque
but not Sidekiq
class GoogleCalendarDeleteEventJob
@queue = :notifications
class << self
def enqueue(appointment_id)
Resque.enqueue(self, appointment_id)
end
def perform(appointment_id)
AppointmentCalendarService.delete_event_for(appointment_id)
end
end
end
So you can call it in any place you need it, like in a controller
def create
if AppointmentEvent.persist_values(params)
GoogleCalendarDeleteEventJob.enqueue(appt_event.id)
...
else
...
end
Are you interested in the details?
Aucun commentaire:
Enregistrer un commentaire