2013-11-16 3 views
1

Я пытаюсь подписаться на фид pubsubhubbub (pshb) на superfeedr. Путь протокол PSHB работы являетсяHTTP-запрос при создании ActiveRecord

  1. вы Отправить POST к концентратору с просьбой подписаться на канал и обеспечить обратный вызов
  2. хаб отправляет GET для обратного вызова для проверки вашего намерения подписаться
  3. вы ответить говоря да, я хочу подписаться
  4. ступицу отвечает подписной проверки

Я бегу сервер локально на мой Dev машине. У меня есть код, который может успешно подписаться на фид, я тестирую его, выполнив его непосредственно в консоли rails. Теперь я создал модель Feed ActiveRecord и хочу автоматически подписываться каждый раз, когда создается новая запись 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 спрашивать (7). Таким образом, концентратор может достичь моего обратного вызова, но по какой-то причине я не получаю GET от хаба до тех пор, пока не истечет время ожидания?

Я новичок в рельсах, поэтому не уверен, как все работает, но я предполагаю, что что-то происходит с параллелизмом запросов в середине создания ActiveRecord. Подписка работает сама по себе, но не во время создания ActiveRecord, поскольку я установил ее в after_create.

Каков правильный способ обработки HTTP-запроса сторонним серверам, если вы хотите сделать это, когда создается запись ActiveRecord?

УКАЗАНИЕ ** в superfeedr api вы можете указать намерение проверки асинхронно. Когда я укажу, что это async, я получаю ответ об успешном ответе, но подписка по-прежнему, похоже, не разбивается на концентратор суперфильтра. Я напрямую свяжусь с superfeedr об этой проблеме, но в целом я хочу знать, как обрабатывать эту ситуацию для API, у которых нет опции async.

+1

Я не стал бы связывать процесс ActiveRecord из-за запроса GET. Если ваш запрос занимает слишком много времени, ваш код зависает, что будет плохо для вашего сервера и всех ваших пользователей. Люди могут даже использовать DOS, поставляя фиктивные записи, которые, как они знают, займут некоторое время. Вместо этого напишите URL-адрес в своей базе данных, а затем запустите поток, который обрабатывает только этот процесс подписки, а затем завершает работу. Или посмотрите на что-то вроде AMQP/RabbitMQ и напишите узел, который обрабатывает задание для вас; Он не повесит ваш сервер Rails, он будет автоматически вставлен в очередь и будет достаточно легким. –

ответ

0

Проблема - хорошо известная проблема с Rails в среде «devlopment», которая допускает только один одновременный HTTP-запрос. Поскольку вы выполняете свой after_create :subscribe_feed во время одного HTTP-запроса, когда Superfeedr пытается проверить ваше намерение, он выдает второй запрос на ваш вход во время первого. Проверка будет зависать до тех пор, пока запрос на подписку не будет выполнен ... срабатывает какой-то тупик.

Решение простое: использовать hub.verify=async параметров при подписке и Superfeedr сначала закрыть заявку на подписку (с 202 статуса) и будет затем вопрос проверка намерения.

Вы также можете удалить параметр hub.verify, так как он по умолчанию асинхронный.

Смежные вопросы