RuboCop Oracleを実装してリリースした。
長年 RDBMS に Oracle (Active Record Oracle enhanced adapter) を使った運用をしているが、これは無停止リリースを行うにあたってのマイグレーションの tip を cop にして含んでおいたもの。
最初の v0.1.0 リリースで含んでいるのは Oracle/OnlineIndex
cop 単品。これは CREATE INDEX
の際に ONLINE
オプションをついていないマイグレーションファイルを検知する cop です。
Oracle/OnlineIndex
cop
データベースのインデックス追加を行う際は ONLINE
オプションを付けないと OLTP (オンライントランザクション処理) が有効にならず、オンライン稼働のままインデックス作成を行おうとするとオンライン処理とそれぞれ処理待ちになりうる (結果としてオンラインサービス影響が起きうる) 。
この Oracle/OnlineIndex
cop の bad と good は以下。options: :online
を付与することで OLTP が有効になる。
# bad add_index :table_name, :column_name # good add_index :table_name, :column_name, options: :online
マイナス面としては OLTP を有効にしたときよりも処理が遅くなるといったことがありうるが、無停止でサービス影響なしで進めるのを第一に ONLINE
オプションを付けておこうという判断をするプロジェクトには有効だと思う。
また Oracle/OnlineIndex
cop のオプションとして MigratedSchemaVersion
というものがある。たとえば、RuboCop Oracle 導入以前に db/migrate/202104130150_add_title_index_to_articles.rb まで本番環境に適用済みであれば、それ以前のマイグレーションファイルへの ONLINE
オプションの付与を検知したくない場合に、適用済みのマイグレーションバージョンを記すことで、適用済みのマイグレーションファイルへの検出を防ぐことができる。
Oracle/OnlineIndex: MigratedSchemaVersion: '202104130150'
git による並列開発で、必ずしもマイグレーションバージョンのタイムスタンプが過去から未来へと流れているわけではないが、だいたいはうまくいくだろう。bin/rails db:migrate:status
あるいはその内部 API を使えばさらに誤検知を防げるだろうが、静的解析の域を超えるので実装はしないことにしている。そのあたりはコードレビュー掛け合わせになるだろう。
開発雑記
RuboCop Oracle の開発構想自体はずいぶんと前からあって、一番の悩みは名前だった。Active Record Oracle enhanced adapter をもう少し前面に出した名前にするか悩んだが、gem で公開するときの名前をシンプルにしたかったのと、gem + RuboCop の世界で Oracle を冠して困るようなことはなかろうとやや大きめの名前だが RuboCop Oracle にした。 また、RuboCop Rails に含めた cop にすることも少しだけ考えたが、Oracle adapter 特化なので独自の gem にした。
そのほか、RuboCop Rails でもマイグレーションファイルへのルール検知をしたいという PR がいくつかあるが、マイグレーションファイルは適用済みかどうかの観点も重要なため取り込めていないものがある。今回の MigratedSchemaVersion
はその課題に対するひとつの習作となっている。デフォルトで db/schema.rb のスキーマバージョンを活用するなど、もう少しリッチにするかもしれない (など、まだ改善の余地がある) 。
あとプロダクト自体のドキュメンテーションはもう少し整えておく予定。