🖥

#Rails + #MySQL / ApplicationRecord.transaction / begin rescue end / C

2020/01/10に公開
class User < ApplicationRecord
  validates_uniqueness_of :unique_id
end

I HOPE IT

def call_inner_transaction(id: , something_wrong: false)
  begin
    ActiveRecord::Base.transaction do
      StripeWebhookSucceededEvent.create!(unique_id: id)
      raise 'SOMETHING WRONG' if something_wrong
      puts '-' * 100
      puts 'EXECUTED!'
      puts '-' * 100
    end
  rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
    puts '*' * 100
    puts "RAISED!"
    puts '*' * 100
    puts e.message
  end
end
dupulicated_id = rand(999_999_999_999)

# EXECUTE
# COMMIT 

SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s)
# [88] pry(main)> SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s)
#    (0.4ms)  BEGIN
#   StripeWebhookSucceededEvent Create (0.7ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('225043383392', '2020-01-09 10:53:13')
# ----------------------------------------------------------------------------------------------------
# EXECUTED!
# ----------------------------------------------------------------------------------------------------
#    (2.5ms)  COMMIT
# => nil

# DUPULICATE and RAISE
# NO EXECUTE
# ROLLBACK
SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s)
# [89] pry(main)> SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s)
#    (0.4ms)  BEGIN
#   StripeWebhookSucceededEvent Create (1.1ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('225043383392', '2020-01-09 10:53:17')
#    (2.6ms)  ROLLBACK
# ****************************************************************************************************
# RAISED!
# ****************************************************************************************************
# Mysql2::Error: Duplicate entry '225043383392' for key 'index_users_on_unique_id': INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('225043383392', '2020-01-09 10:53:17')
# => nil


# DUPULICATE and RAISE before SOMETHING WRONG
# NO EXECUTE
# ROLLBACK
SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s, something_wrong: true)
# [90] pry(main)> SomeClass.new.call_inner_transaction(id: dupulicated_id.to_s, something_wrong: true)
#    (0.4ms)  BEGIN
#   StripeWebhookSucceededEvent Create (2.6ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('225043383392', '2020-01-09 10:53:24')
#    (3.3ms)  ROLLBACK
# ****************************************************************************************************
# RAISED!
# ****************************************************************************************************
# Mysql2::Error: Duplicate entry '225043383392' for key 'index_users_on_unique_id': INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('225043383392', '2020-01-09 10:53:24')
# => nil

# SOMETHING WRONG
# NO DUPULICATE
# NO EXECUTE
# RAISE AND ROLLBACK
SomeClass.new.call_inner_transaction(id: rand(999_999_999_999).to_s, something_wrong: true)
# [91] pry(main)> SomeClass.new.call_inner_transaction(id: rand(999_999_999_999).to_s, something_wrong: true)
#    (0.9ms)  BEGIN
#   StripeWebhookSucceededEvent Create (1.0ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('357583484588', '2020-01-09 10:53:28')
#    (3.0ms)  ROLLBACK
# RuntimeError: SOMETHING WRONG
# from (pry):120:in `block in call_inner_transaction'

I DO NOT HOPE IT

def call_outer_transaction(id: , something_wrong: false)
  ActiveRecord::Base.transaction do
    begin
      StripeWebhookSucceededEvent.create!(unique_id: id)
      raise 'SOMETHING WRONG' if something_wrong
      puts '-' * 100
      puts 'EXECUTED!'
      puts '-' * 100
    rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
      puts '*' * 100
      puts "RAISED!"
      puts '*' * 100
      puts e.message
    end
  end
end
dupulicated_id = rand(999_999_999_999)

# EXECUTE
# COMMIT
SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s)
# [93] pry(main)> SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s)
#    (0.4ms)  BEGIN
#   StripeWebhookSucceededEvent Create (0.6ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('64910455241', '2020-01-09 10:54:18')
# ----------------------------------------------------------------------------------------------------
# EXECUTED!
# ----------------------------------------------------------------------------------------------------
#    (4.7ms)  COMMIT
# => nil



# DUPLUCATED AND RAISED
# NO EXECUTE
# BUT COMMIT HAPPENS
SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s)
# [94] pry(main)> SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s)
#    (0.5ms)  BEGIN
#   StripeWebhookSucceededEvent Create (6.4ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('64910455241', '2020-01-09 10:54:26')
# ****************************************************************************************************
# RAISED!
# ****************************************************************************************************
# Mysql2::Error: Duplicate entry '64910455241' for key 'index_users_on_unique_id': INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('64910455241', '2020-01-09 10:54:26')
#    (5.4ms)  COMMIT
# => nil

# DUPLUCATED AND RAISED
# NO EXECUTE
# BUT COMMIT HAPPENS

SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s, something_wrong: true)
# [95] pry(main)> SomeClass.new.call_outer_transaction(id: dupulicated_id.to_s, something_wrong: true)
#    (1.0ms)  BEGIN
#   StripeWebhookSucceededEvent Create (1.3ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('64910455241', '2020-01-09 10:54:32')
# ****************************************************************************************************
# RAISED!
# ****************************************************************************************************
# Mysql2::Error: Duplicate entry '64910455241' for key 'index_users_on_unique_id': INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('64910455241', '2020-01-09 10:54:32')
#    (4.3ms)  COMMIT
# => nil

# SOMETHING WRONG
# NO DUPULICATE
# NO EXECUTE
# BUT RAISE AND ROLLBACK

SomeClass.new.call_outer_transaction(id: rand(999_999_999_999).to_s, something_wrong: true)
# [96] pry(main)> SomeClass.new.call_outer_transaction(id: rand(999_999_999_999).to_s, something_wrong: true)
#    (0.5ms)  BEGIN
#   StripeWebhookSucceededEvent Create (0.8ms)  INSERT INTO `users` (`unique_id`, `created_at`) VALUES ('710309047775', '2020-01-09 10:54:37')
#    (2.4ms)  ROLLBACK
# RuntimeError: SOMETHING WRONG
# from (pry):137:in `block in call_outer_transaction'

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2930

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

Twitter

https://twitter.com/YumaInaura

公開日時

2020-01-10

Discussion