From a604962a50f630d58b85c88e1efd5e73fbdb09f8 Mon Sep 17 00:00:00 2001 From: n atta kusi adusei Date: Mon, 12 Aug 2024 15:00:18 +0000 Subject: [PATCH] Run delete operation in a transaction (#1055) * Run delete operations in a transaction * Add `after_commit` callback to delete operations --- .../delete_operation_callbacks_spec.cr | 7 +++++ src/avram/delete_operation.cr | 28 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/spec/avram/operations/delete_operation_callbacks_spec.cr b/spec/avram/operations/delete_operation_callbacks_spec.cr index cd79e2d6c..8b6cc0e58 100644 --- a/spec/avram/operations/delete_operation_callbacks_spec.cr +++ b/spec/avram/operations/delete_operation_callbacks_spec.cr @@ -22,6 +22,8 @@ private class DeleteOperationWithCallbacks < User::DeleteOperation mark_callback("after_delete_in_a_block with #{deleted_user.name}") end + after_commit :run_after_commit + private def update_number mark_callback("before_delete_update_number") end @@ -29,6 +31,10 @@ private class DeleteOperationWithCallbacks < User::DeleteOperation private def notify_complete(deleted_user) mark_callback("after_delete_notify_complete is #{deleted_user.name}") end + + private def run_after_commit(deleted_user) + mark_callback("after_commit_#{deleted_user.name.underscore}") + end end describe "Avram::DeleteOperation callbacks" do @@ -41,6 +47,7 @@ describe "Avram::DeleteOperation callbacks" do operation.callbacks_that_ran.should contain "before_delete_in_a_block" operation.callbacks_that_ran.should contain "after_delete_notify_complete is Jerry" operation.callbacks_that_ran.should contain "after_delete_in_a_block with Jerry" + operation.callbacks_that_ran.should contain "after_commit_jerry" end end end diff --git a/src/avram/delete_operation.cr b/src/avram/delete_operation.cr index e99085d53..e4a84b4a4 100644 --- a/src/avram/delete_operation.cr +++ b/src/avram/delete_operation.cr @@ -35,18 +35,32 @@ abstract class Avram::DeleteOperation(T) T.name.underscore end + delegate :database, :table_name, :primary_key_name, to: T + def delete : Bool before_delete if valid? - result = delete_or_soft_delete(@record) - @record = result - after_delete(@record) - publish_delete_success_event - mark_as_deleted + transaction_committed = database.transaction do + @record = delete_or_soft_delete(record) + after_delete(record) + true + end + + if transaction_committed + mark_as_deleted + after_commit(record) + publish_delete_success_event + true + else + mark_as_failed + publish_delete_failed_event + false + end else - publish_delete_failed_event mark_as_failed + publish_delete_failed_event + false end end @@ -88,6 +102,8 @@ abstract class Avram::DeleteOperation(T) def after_delete(_record : T); end + def after_commit(_record : T); end + # :nodoc: def publish_delete_failed_event Avram::Events::DeleteFailedEvent.publish(