人間とブラウザーを使用した通常のテストでは、すべてが期待どおりに機能します。ただし、rspec を使用すると、次のことがわかります。
D, [2014-08-16T13:48:09.510013 #19418] DEBUG -- : SQL (0.6ms) UPDATE "system_flights_cacheds" SET "client_stuff" = '{"captcha":"656556"}' WHERE "system_flights_cacheds"."guid" = '5647046e-4194-498e-a0d7-512614b147d8'
しかし、実際に私のデータベース レコードが更新されていないとは信じられません。以前は .save を使用していましたが、実際には成功せず、SAVEPOINT が作成されました。
問題のある私のコードは、基本的に API エンドポイントです。
cache = System::Flights::Cached.search_cache options
# update database, when the captcha is present. this way, the worker
# when updating the database can see the changes and act accordingly!
if cache && params[:captcha]
# remember, anyone can (basically) see the captcha. thus,
# this is a bit paranoid, only allow captcha update
# if the user is same! in the json, if not forgotten,
# captcha is only displayed when the user_id is equal
server_stuff = cache.server_stuff.with_indifferent_access
if server_stuff[:user_id] == current_user.id
cache.time_renewed = 10
cache.client_stuff_will_change!
cache.client_stuff ||= {}
cache.client_stuff[:captcha] = params[:captcha]
# cache.save!
cache.update_columns(client_stuff: cache.client_stuff)
end
else
# only spawn worker if there is no captcha parameter passed
spawn_search_worker({user_id: current_user.id, options: options})
end
クライアントはいつでもこれに到達でき、ワーカーにまたがります。新しいレコードが既にデータベースにあるが、is_processed が false の場合、ワーカーは終了します。したがって、これを複数回呼び出すことは、作業が完了したかどうかのステータスを確認する手段としても問題ありません。
ワーカーは、クライアントがキャプチャを入力するのを待ちます。したがって、基本的に次のことを行うWaitableLoginのようなクラスがあります。
max_repeat = 3 # 14
# annul flag, if set to true, the data will not get persisted.
annul = false
while max_repeat > 0
# interval of 5 secs that worker can check the database
sleep 5
max_repeat -= 1
# break if captcha already entered by client
# seek from the database if the client has posted
# the captcha text
cache = System::Flights::Cached.search_cache options
client_stuff = nil
client_stuff = cache.client_stuff.with_indifferent_access if cache && cache.client_stuff
if client_stuff && client_stuff[:captcha]
captcha_text = client_stuff[:captcha]
airline.fill_captcha(captcha_text).finalize_login
puts "SOMEHOW I AM HERE: #{captcha_text}"
# remove all server's stuff
cache.server_stuff_will_change!
cache.server_stuff.clear
cache.save!
annul = airline.in_login_page?
end
end
そのため、WaitableLogin は client_stuff が更新されているかどうかを確認します。そうであれば、クライアントがキャプチャを送信したことがわかります (エンドポイントを介して、ワーカーはキャプチャがパラメーターであるかどうかを確認し、キャプチャ フィールドがある場合はデータベースを更新します)。
その後、制御はワーカーに戻されました。ファイル全体のコードの多くの部分でキャッシュを使用する多くのコードがあることがわかります。キャッシュは単なる変数名であり、Rails などでのセマンティックな意味とは何の関係もありません。
ブラウザで正常に実行すると、問題はありません。実際、.save を使用しても SAVEPOINT はありません。そのSAVEPOINTでどこかにバグが発生しているのではないかと思ったので、.update_columnsを使ってみることにしました。しかし、やはり成功しませんでした。
これはテストがどのように見えるかです before(:each) do System::Flights::Cached.delete_all end
describe "requests" do
it "should process 2a1c1i" do
cached = nil
post("/api/v1/x.json", {
access_token: CommonFlightData::ACCESS_TOKEN,
business_token: CommonFlightData::BUSINESS_TOKEN,
captcha: ""
}.merge!(CommonFlightData.oneway_1a(from: "8-9-2014")))
puts "enter the captcha: "
captcha = STDIN.gets.chomp
puts "Entered: #{captcha}"
post("/api/v1/x.json", {
access_token: CommonFlightData::ACCESS_TOKEN,
business_token: CommonFlightData::BUSINESS_TOKEN,
captcha: captcha
}.merge!(CommonFlightData.oneway_1a(from: "8-9-2014")))
sleep 10
だから私は何が欠けているのか、疲れました。エラーは発生しませんでした。update_columns の後に .inspect を確認すると、すべて更新されているようです。しかし、データベースを見ると、何も更新されていません。
編集:楽観的なロックができるようにlock_versionを配置しました(デフォルトでは、そう思います)。そして、予想通り、それは 2 に設定されていました。
編集 2: コードがキャプチャを要求しているときに、Rails コンソールから編集をコマンドすると、IT はデータを更新します。SO、api エンドポイントを実行してキャプチャを送信する RSpec 仕様が行を更新しないのはなぜですか。すべての実際の非仕様コードは、細かく実行されます。