はじめに
トラブル解決というわけでもなく,格闘の結果わかったことを書きます.
とある予約システムを作っていて,Submit毎のリダイレクトがうざいので非同期にしようと考えてremote: true
とかやって周りを調整してました.
お客さんが触る部分はわりとすんなり非同期にできたんですけど,管理画面(ステータス表示・変更)を非同期にしたら500(Internal Server Error)吐きまして,そういう話です.
環境
- Rails 5.0.0.1
- development
- SQLite3
超適当ですすみません.
症状と格闘の結果
冒頭で書いた通り,500を吐かれました.これはブラウザ側で見たエラーコンソール.じゃあRailsのログには何が残っていたかというと,
... (1.0ms) rollback transaction ... ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: commit transaction): ...
死ぬほど省いてますがこんな感じ.rollback?! BusyException?! リダイレクトしないようにしただけで?!と思いながら格闘開始.
database is locked
から見るに,アクセスが衝突したんだろうな〜と思いながらエラー名コピペサーチでビンゴ.なんで衝突したのかの究明へ.
- 作成Submitはめちゃすんなりできる
- 更新Submit&Redirectはいける
- 更新Submitは死ぬ
これらとのコードの違いを見ていきながらデバッグしていった.
得られた結果
UPDATEのトランザクションは時間がかかる(体感)から,すぐ参照するとトランザクション中にアクセスすることになりコミットと衝突してしまう.
SQLiteが並行アクセスをサポートしていない(参照)から衝突すると死ぬ.Production(PostgreSQL)では死なないのでは?
という感じになりました.productionで試しても良かったのですが,「まぁ管理画面くらいリダイレクトしようや」とサボローがいったので保留. 他に読んだ記事はこれくらい
最近テストコードは書くようになりましたが,デバッグは雑ってよく言われるのでおそらく解決策は存在すると思うのでもう少し格闘します.
おわりに
Atomのterminal-plusの記事がよく読まれていてめっちゃ嬉しいのでトラブル解決系書きたいんですけど,そこまでトラブルに出会わないので書けません. そういえばMacBook Pro(Late-2016)買いました.またなんか開発したいです. ではまた.