私はMonogDBでこのようなことを達成しようとしています:
require 'base64'
require 'mongo'
class MongoDBQueue
def enq(thing)
collection.insert({ payload: Base64.encode64(Marshal.dump(thing))})
end
alias :<< :enq
def deq
until _r = collection.find_and_modify({ sort: {_id: Mongo::ASCENDING}, remove: true})
Thread.pass
end
return Marshal.load(Base64.decode64(_r["payload"]))
end
alias :pop :deq
private
def collection
# database, collection & mongodb index semantics here
end
end
当然のことながら、利用可能なメモリを破壊しないディスクでバックアップされたキューが Ruby に必要です。これを、デフォルトでクラスを使用する Anemone Web スパイダー フレームワークで使用しています。クラスQueue
を使用できるフォークがありますが、 「ページキュー」と「リンクキュー」SizedQueue
のSizedQueue
両方で、おそらくページをデキューして処理しようとしているためにデッドロックが発生することが多く、新しいリンクが見つかり、その状況を調整できません。
Redis キューの既存の実装もありますが、このマシンで使用可能なメモリをすべて使い果たします (使用可能なメモリは 16Gb であるため、簡単ではありません)。
そのため、この MongoDB バックエンドを使用したいのですが、実装が非常識だと思います。恐ろしい解決策のThread.pass
ように感じますが、Anemone はマルチスレッドであり、MongoDB は読み取りのブロックをサポートしていないため、トリッキーな状況です。
ここに私の参照があります:
anemone の Redis キューの実装: https://github.com/chriskite/anemone/blob/queueadapter/lib/anemone/queue/redis.rb
MongoDB の findAndModify: http://www.mongodb.org/display/DOCS/findAndModify+Command
質問:
- これがどれほど正気であるかについて、誰でもコメントできますか
sleep
?sleep
- 私はおそらくすべきでしょう
Thread.pass
かsleep
?(そうではないと思います、上記を参照してください) - MongoDB ブロックから読み取るようにできますか? ここでその話がありましたが、何も起こりませんでした: https://groups.google.com/forum/?fromgroups=#!topic/mongodb-user/rqnHNFXaZ0w