LoginSignup
2
2

More than 5 years have passed since last update.

ruote - implementing a storage を訳してみた

Last updated at Posted at 2012-04-07

(2012-04-01) オレオレ訳。後半は力尽きてかなりいい加減。


ストレージの実装

Ruote は、メモリ上とファイルシステム上の二種類のストレージを持つ。その他のストレージも利用可能であるが、それぞれ長所、短所がある。

格納するオブジェクト(式、ワークアイテム、エラー、スケジュール、...)に応じて異なるストレージを選択する複合型のストレージもある。

独自のストレージを実装する必要がある場合もある。このページは助けになるべきである。(メーリングリスト上で叫んでいない場合)

ストレージの実装は、ストレージ インターフェースに従う必要がある。

少し歴史を

ストレージは、ruote 2.1.x の核心である。

engine = Ruote::Engine.new(Ruote::Worker.new(ThatStorage.new(info)))
  # or
engine = Ruote::Engine.new(ThatStorage.new(info))

ワーカーとエンジンはストレージが必要とする。それらは、共有ストレージを介して連携する。

Ruote は永続性を必要とする。プロセスは、エンジンよりも寿命が長い場合がある。エンジンがダウンした場合、プロセスはストレージに格納される。ワーカーが復帰すると、プロセスは再開されなければならない。

Ruote 2.1.x の複数ワーカーは、ワーカーが互いに上書きや削除するのを防止する必要性をもたらした。

ドキュメント

Ruote 2.1.x のストレージは、CouchDB に強く影響を受けている。特に、ドキュメントとバージョンの概念に影響を受けている。

Ruote は全てのデータをドキュメントとして表現する。ドキュメントは JSON シリアライズ可能なハッシュである。“_id” 、“type” と “_rev” を項目として持つ。

‘type’ は、“expressions” 、“errors” 、“workitems” 、“schedules” のような文字列である。

‘_id’ は、ドキュメント識別子である。

ドキュメント タイプ

ドキュメントには、7+1 種類のタイプがある。

タイプ 説明
expressions プロセス インスタンスの部品
msgs expressions からの/への ‘messages’
schedules 後に処理するためにスケジュールされた msgs
errors プロセス実行中に発生した errors
variables エンジン グローバルな変数
configurations エンジンのコンフィグレーション
workitems StorageParticipant ワークアイテム
history Ruote::StorageHistoryを使っている場合)

一貫性

Ruote は複数のドキュメントを確保する。ストレージの実装が排他的更新を提供できない場合、単一のワーカーに制限される。

ワーカーの詳細については コンフィグレーション ページ を参照のこと。

インターフェース

#--
# 主なメソッド
#++

# ドキュメントの格納
#
# opts:
# ... TODO ...
#
# 戻り値:
# * true ドキュメントが削除されていた場合
# * a document バージョン(rev)が変更された場合
# * nil 保存が成功した場合
#
def put(doc, opts={})
end

# ドキュメント タイプとキー(_id)によるドキュメントの取得
#
def get(type, key)
end

# ドキュメントの削除
#
# 戻り値:
# * true 既に削除済みの場合
# * a document 与えられたドキュメントのバージョン(rev)が現在のバージョンと異なる場合
#   document
# * nil 削除が成功した場合
#
def delete(doc)
end

# 特定のタイプの複数のドキュメントを取得する
#
# 入力:
# - key が指定されない場合、全てのドキュメントを返す
# - Array(key) にドキュメントの _id がマッチするものを返す
#
# opts:
# [:descending]    _id で降順でソートする
# [:count]         件数を返す
# [:skip]          X 件スキップする
# [:limit]         X 件に制限する
#
# 戻り値:
# * An Integer (:count が指定された場合)
# * An array of documents
#
def get_many(type, key=nil, opts={})
end

# 指定されたドキュメント タイプの _id のリストを返す
#
def ids(type)
end

#--
# 補助的なメソッド
#++

# 全ての msgs 、schedules 、errors 、expressions と workitems を削除する
#
# It's used mostly when testing workflows, usually when cleaning the
# engine/storage before a workflow run.
#
def clear
end

# ストアをクリアする
#
def purge!
end

# 新しいドキュメント タイプを追加する。いくつかのストレージでは必要
#
def add_type(type)
end

# 指定されたタイプのドキュメントを削除する
#
def purge_type!(type)
end

モデルとしての実装

実装の例。 hash_storage.rb

テスト

ストレージの実装は、ユニットテストと機能テストを実施されるべきだ。複数ワーカーで利用される場合、同時テストも実施すべきだ。

テストは、ruote/ ディレクトリから実行される。“redis” や “sequel” といった実装名を持つ拡張子を渡すと、テストは自動的に行われる。

このセクションの残りでは、“ruote-pasta” という実装名で、ruote-pasta/ ディレクトリに格納したと仮定する。

ストレージ実装は、“new_storage” メソッドを含む test/functional_connection.rb を提供する必要がある。これは、テストのためにストレージをセットアップするための ruote テストスイートを含む。ruote-redisruote-sequel の functional_connection.rb を参照のこと。

ユニット テスト

ruote のユニットテストにおいて、ストレージのテスト関連はこれだけである。

$ ruby test/unit/storage.rb -- --pasta

このテストをグリーンにすることが、ストレージ開発の最初の目標だ。

機能テスト

ストレージ実装は全ての機能テストを通過すべきだ。

$ ruby test/functional/test.rb -- --pasta

いくつかのダングリングテストに困難がある場合、メーリングリスト を参照のこと。

同時テスト(複数のワーカー)

複数のワーカーが稼働しているように ruote ストレージをテストする 3つのテストがある。それらは test/functional/ の下にあり、“ct_” が先頭についている。

ct_ テストを200回実行しても失敗しなければ、複数ワーカーで問題ないといえる。

$ ./test/looper.sh test/functional/ct_0_concurrence.rb -- --pasta 200
$ ./test/looper.sh test/functional/ct_1_iterator.rb -- --pasta 200
$ ./test/looper.sh test/functional/ct_2_cancel.rb -- --pasta 200

これらのテストはワーカーの間で衝突を起こす。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2