AP4Rの連載読みながらやってみた。。。が『Mysql::Error: Lost connection to MySQL server during query: ROLLBACK』

非同期処理が必要になったところで、gihyo.jpに「AP4RRubyで非同期メッセージング」という記事をみつけた。
やってみた。

でも、第3回 SAF機能とテストサポートによる安心非同期 (3/5)で、記事の通りに動かない・・・

class AsyncShopController < ApplicationController
  (省略)
  def order
    begin
      ap4r.transaction do
        @order = Order.new(params[:order])
        @order.save!

        ap4r.async_to({:action => 'payment'},
                      {:order_id => @order.id})
        raise "for SAF test"
        flash[:notice] = 'Order was successfully created.'
        redirect_to :action => 'index'
      end
    rescue Exception
      flash[:notice] = 'Order was failed.'
      render :action => 'order_form'
    end
  end
  (省略)
end

のところで、

(1)async_shop/order 1回目

  • 「raise "for SAF test"」でrescue節に
  • Order 追加されない
  • Ap4r::StoredMessage 追加されてる

(2)async_shop/order 2回目

  • Mysql::Error: Lost connection to MySQL server during query: ROLLBACK」が発生
  • Order 追加されてる
  • Ap4f::StoredMessage 追加されてる

どちらの場合も、Fowardの前に例外が発生してるのでメッセージが送信されることはありませんが、

(1)Ap4r::StoredMessageは存在。でも該当のorderはない。
(2)エラーって出るのにorderができてしまう。Ap4r::StoredMessageもある。Fowardだけしてない。


どゆこと?


PostgreSQLでも試してみましたが、やはり2度目で「PGError: closed connection: ROLLBACK」となるようです。
なんか間違えたかな??

その後

# vendor/plugins/ap4r/lib/async_helper.rb

(略)

 def transaction_with_saf(active_record_class = ::Ap4r::StoredMessage, *objects, &block)

  Thread.current[:use_saf] = true
  Thread.current[:stored_messages] = {}
  # store                                                                                                        
  active_record_class ||= ::Ap4r::StoredMessage
  active_record_class.transaction(*objects, &block)

  # forward
  (略)

ということは、Orderでトランザクションを使うなら、

ap4r.transaction(Order) do
  
end

なのでは。

ためしにやってみたら、

  • エラーが発生しなくなった
    • Orderができなくなった
  • やっぱりAp4r::StoredMessageだけは存在


うーん、よくわからんしプラグインは使わず自前で実装したほうがいいかなぁ