ActiveRecord创建期间的HTTP请求

时间:2013-11-16 00:02:44

标签: ruby-on-rails ruby concurrency pubsubhubbub superfeedr

我正在尝试订阅superfeedr上的pubsubhubbub(pshb)Feed。 pshb协议的工作方式是

  1. 您将POST发送到集线器,请求订阅Feed并提供回叫
  2. 集线器向您的回调发送GET以验证您的订阅意图
  3. 你回答说是的我想订阅
  4. 集线器响应订阅验证
  5. 我在开发机器上本地运行服务器。我有可以成功订阅feed的代码,我通过直接在rails控制台中执行它来测试它。我现在创建了一个Feed ActiveRecord模型,并希望每次创建新的Feed记录时都自动订阅。我在Feed模型中添加了一个ActiveRecord回调

    after_create :subscribe_feed
    

    现在当我创建一个活动记录时,我看到正确的HTTP请求消失,然后有一个很长的挂起(大约5秒,日志中没有任何反应),然后来自pshb服务器的响应说明我的回调可以没有达到。

    以下是日志(我为参考点添加的数字)

    (1)   (0.1ms)  begin transaction
    (2)  SQL (4.4ms)  INSERT INTO "feeds" ("created_at", "updated_at", "url") VALUES (?, ?, ?)  [["created_at", Fri, 15 Nov 2013 23:08:39 UTC +00:00], ["updated_at", Fri, 15 Nov 2013 23:08:39 UTC +00:00], ["url", "http://push-pub.appspot.com/feed"]]
    
    (3) pshb subscribe parameters: {:headers=>{"Accept"=>"application/json"}, :body=>{"hub.mode"=>"subscribe", "hub.verify"=>"sync", "hub.callback"=>"http://...myserver.../pub_sub/callback", "hub.topic"=>"http://push-pub.appspot.com/feed", "hub.verify_token"=>"superfeedtest", "format"=>"json"}}
    
    (4) # ABOUT 5 SECOND WAIT
    
    (5) Subscribe Response: #<HTTParty::Response:0x7fd2180cd978 parsed_response="Your callback couldn't be reached.\n", @response=#<Net::HTTPUnprocessableEntity 422 Unprocessable Entity readbody=true>, @headers={"server"=>["nginx/0.8.52"], "date"=>["Fri, 15 Nov 2013 23:08:44 GMT"], "content-type"=>["text/plain; charset=utf-8"], "connection"=>["close"], "status"=>["422 Unprocessable Entity"], "x-runtime"=>["10057"], "content-length"=>["35"], "set-cookie"=>["_superfeedr_session=BAh7BzoMdXNlcl9pZGkC%2BIY6D3Nlc3Npb25faWQiJTBiMDExZGYzNzU4Mjk0MTMxNjc4NmE0OTg3MDhlMjJk--85d29756ae4b5ae9464630741372af7656f3894b; path=/; HttpOnly"], "cache-control"=>["no-cache"], "pubsubhubbub-version"=>["0.3"]}>
    
    (6)   (7.2ms)  commit transaction
    Redirected to http://67.180.177.165/feeds/28
    Completed 302 Found in 10695ms (ActiveRecord: 11.6ms)
    
    (7) Started GET "/pub_sub/callback?hub.challenge=437c4b3b47aa1dbf4072a2d8abb5c39a&hub.lease_seconds=315360000&hub.mode=subscribe&hub.topic=http%3A%2F%2Fpush-pub.appspot.com%2Ffeed&hub.verify_token=superfeedtest" for 173.255.193.75 at 2013-11-15 15:08:50 -0800
    

    你可以看到在响应之后发生了提交事务(6),然后来自要求验证的phsb服务器的GET进入(7)。所以集线器可以到达我的回调,但由于某种原因,我没有收到来自集线器的GET,直到它超时后?

    我是rails的新手,所以不确定它是如何工作的,但我猜测在ActiveRecord创建过程中请求的并发性正在发生。订阅可以单独工作,但不能在ActiveRecord创建期间工作,因为我已经在after_create中设置了它。

    如果要在创建ActiveRecord条目时执行此操作,处理对第三方服务器的HTTP请求的正确方法是什么?

    注意**在superfeedr api中,您可以指定异步发生的验证意图。当我将其指定为异步时,我确实得到了成功响应,但订阅似乎仍然没有在superfeedr的集线器上创建。我会直接联系superfeedr来解决这个问题,但总的来说我想知道如何处理没有异步选项的API的情况。

1 个答案:

答案 0 :(得分:0)

问题是Rails在“devlopment”环境中的一个众所周知的问题,它只允许一个单独的并发HTTP请求。由于您在一次HTTP请求期间执行after_create :subscribe_feed,当Superfeedr尝试验证您的意图时,它会在期间向您的输入发出第二个请求。验证将一直挂起,直到订阅请求完成...触发某种死锁。

解决方案很简单:订阅时使用hub.verify=async参数,Superfeedr将首先关闭订阅请求(状态为202),然后发出意图验证。

您也可以删除hub.verify参数,因为默认情况下它是异步的。