1

在使用人和浏览器的正常测试中,一切都按预期工作。但是,当我使用 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 时,worker 将退出。因此,多次调用它是可以的,这也是检查工作是否完成的一种方法。

工作人员将等待客户输入验证码。所以,我们有像 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 是否已更新。如果是,那么我们知道客户端已经提交了验证码(通过端点,工作人员将检查验证码是否为参数,如果有验证码字段,则更新数据库)。

然后将控制权转移回 Worker。您可以看到有很多代码在跨文件的许多代码部分使用缓存,缓存只是变量名,与它在 Rails 中的语义含义无关。

当我在浏览器上正常运行时,我看不到任何问题。事实上,即使我使用 .save,也没有 SAVEPOINT。我想,它在某处使用该 SAVEPOINT 创建了一些错误,所以我决定尝试使用 .update_columns。但是,再一次,没有成功。

这是测试之前的样子(: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控制台命令编辑,它会更新数据。所以,为什么运行 api 端点以提交验证码的 RSpec 规范不会更新该行。所有现实生活中没有原始规范的代码都被很好地执行。

4

0 回答 0