Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store canonical recurring tasks in the DB #272

Merged
merged 11 commits into from
Aug 7, 2024
Prev Previous commit
Next Next commit
Fix persisting tasks for PostgreSQL on concurrent INSERTs
PostgreSQL fails and aborts the current transaction when it hits
a duplicate key conflict during two concurrent INSERTs for the same
value of an unique index. We need to explicitly indicate unique_by
to ignore duplicate rows by this value when inserting
rosa committed Aug 6, 2024
commit 04a1d93b3ebc8ff94f8906889c3bde2e50096beb
11 changes: 11 additions & 0 deletions app/models/solid_queue/recurring_task.rb
Original file line number Diff line number Diff line change
@@ -19,6 +19,17 @@ def wrap(args)
def from_configuration(key, **options)
new(key: key, class_name: options[:class], schedule: options[:schedule], arguments: options[:args])
end

def create_or_update_all(tasks)
if connection.supports_insert_conflict_target?
# PostgreSQL fails and aborts the current transaction when it hits a duplicate key conflict
# during two concurrent INSERTs for the same value of an unique index. We need to explicitly
# indicate unique_by to ignore duplicate rows by this value when inserting
upsert_all tasks.map(&:attributes_for_upsert), unique_by: :key
else
upsert_all tasks.map(&:attributes_for_upsert)
end
end
end

def delay_from_now
2 changes: 1 addition & 1 deletion lib/solid_queue/dispatcher/recurring_schedule.rb
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ def task_keys

private
def persist_tasks
SolidQueue::RecurringTask.upsert_all configured_tasks.map(&:attributes_for_upsert), record_timestamps: true
SolidQueue::RecurringTask.create_or_update_all configured_tasks
end

def reload_tasks