From 2161cb8f90b8596ade9fe8f5d1f955a95a86b9f1 Mon Sep 17 00:00:00 2001 From: Arnaud Levy <contact@arnaudlevy.com> Date: Thu, 7 Sep 2023 17:30:11 +0200 Subject: [PATCH] gem --- Gemfile | 1 + Gemfile.lock | 3 + config/initializers/delayed_jobs.rb | 12 --- ...907152751_add_signature_to_delayed_job.rb} | 6 +- db/schema.rb | 2 +- lib/delayed_duplicate_prevention_plugin.rb | 73 ------------------- 6 files changed, 9 insertions(+), 88 deletions(-) rename db/migrate/{20230907085800_add_key_to_delayed_jobs.rb => 20230907152751_add_signature_to_delayed_job.rb} (53%) delete mode 100644 lib/delayed_duplicate_prevention_plugin.rb diff --git a/Gemfile b/Gemfile index 53b050864..bbcc91023 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ gem "country_select" gem "csl-styles", "~> 2.0" gem "curation"#, path: "../../arnaudlevy/curation" gem "delayed_job_active_record" +gem "delayed_job_prevent_duplicate" gem "delayed_job_web" gem "devise" gem "devise-i18n" diff --git a/Gemfile.lock b/Gemfile.lock index ec027c15b..6657633f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -182,6 +182,8 @@ GEM delayed_job_active_record (4.1.7) activerecord (>= 3.0, < 8.0) delayed_job (>= 3.0, < 5) + delayed_job_prevent_duplicate (0.1.0) + delayed_job (>= 3.0, < 5) delayed_job_web (1.4.4) activerecord (> 3.0.0) delayed_job (> 2.0.3) @@ -599,6 +601,7 @@ DEPENDENCIES csl-styles (~> 2.0) curation delayed_job_active_record + delayed_job_prevent_duplicate delayed_job_web devise devise-i18n diff --git a/config/initializers/delayed_jobs.rb b/config/initializers/delayed_jobs.rb index 9fdb383d0..1ed52dd7c 100644 --- a/config/initializers/delayed_jobs.rb +++ b/config/initializers/delayed_jobs.rb @@ -3,15 +3,3 @@ Delayed::Worker.queue_attributes = { low_priority: { priority: 10 }, imports: { priority: 5 } } - -# Avoid duplicates - -# https://groups.google.com/g/delayed_job/c/gZ9bFCdZrsk#2a05c39a192e630c -# https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/backend/base.rb -# https://github.com/ignatiusreza/activejob-trackable - -# based on https://gist.github.com/synth/fba7baeffd083a931184 -require 'delayed_duplicate_prevention_plugin' - -Delayed::Backend::ActiveRecord::Job.send(:include, DelayedDuplicatePreventionPlugin::SignatureConcern) -Delayed::Worker.plugins << DelayedDuplicatePreventionPlugin \ No newline at end of file diff --git a/db/migrate/20230907085800_add_key_to_delayed_jobs.rb b/db/migrate/20230907152751_add_signature_to_delayed_job.rb similarity index 53% rename from db/migrate/20230907085800_add_key_to_delayed_jobs.rb rename to db/migrate/20230907152751_add_signature_to_delayed_job.rb index b500645e2..84df91178 100644 --- a/db/migrate/20230907085800_add_key_to_delayed_jobs.rb +++ b/db/migrate/20230907152751_add_signature_to_delayed_job.rb @@ -1,6 +1,8 @@ -class AddKeyToDelayedJobs < ActiveRecord::Migration[7.0] +# frozen_string_literal: true + +class AddSignatureToDelayedJob < ActiveRecord::Migration[7.0] def change add_column :delayed_jobs, :signature, :string add_column :delayed_jobs, :args, :text end -end +end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index a2aba470b..25f9caafe 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_09_07_085800) do +ActiveRecord::Schema[7.0].define(version: 2023_09_07_152751) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" diff --git a/lib/delayed_duplicate_prevention_plugin.rb b/lib/delayed_duplicate_prevention_plugin.rb deleted file mode 100644 index 43bf45d0b..000000000 --- a/lib/delayed_duplicate_prevention_plugin.rb +++ /dev/null @@ -1,73 +0,0 @@ -require 'delayed_job' -class DelayedDuplicatePreventionPlugin < Delayed::Plugin - - module SignatureConcern - extend ActiveSupport::Concern - - included do - before_validation :add_signature - validate :prevent_duplicate - end - - private - - def add_signature - self.signature = generate_signature - self.args = self.payload_object.args - end - - def generate_signature - pobj = payload_object - if pobj.object.respond_to?(:id) and pobj.object.id.present? - sig = "#{pobj.object.class}" - sig += ":#{pobj.object.id}" - else - sig = "#{pobj.object}" - end - - sig += "##{pobj.method_name}" - return sig - end - - def prevent_duplicate - if DuplicateChecker.duplicate?(self) - Rails.logger.warn "Found duplicate job(#{self.signature}), ignoring..." - errors.add(:base, "This is a duplicate") - end - end - end - - class DuplicateChecker - attr_reader :job - - def self.duplicate?(job) - new(job).duplicate? - end - - def initialize(job) - @job = job - end - - def duplicate? - possible_dupes.any? { |possible_dupe| args_match?(possible_dupe, job) } - end - - private - - def possible_dupes - possible_dupes = Delayed::Job.where(attempts: 0, locked_at: nil) # Only jobs not started, otherwise it would never compute a real change if the job is currently running - .where(signature: job.signature) # Same signature - possible_dupes = possible_dupes.where.not(id: job.id) if job.id.present? - possible_dupes - end - - def args_match?(job1, job2) - # TODO: make this logic robust - normalize_args(job1.args) == normalize_args(job2.args) - end - - def normalize_args(args) - args.kind_of?(String) ? YAML.load(args) : args - end - end -end \ No newline at end of file -- GitLab