Рабочий не может найти недавно добавленную запись
-
19-09-2019 - |
Вопрос
Я использую Starling и Workling для обработки фоновых задач в моем приложении, аукционном сайте в стиле Swoopo.В этом случае фоновой задачей является система уведомлений, которая отслеживает аукционы и уведомляет победителя.Монитор вызывается при создании объекта аукциона.Моя проблема в том, что мой код мониторинга не может найти аукцион, который он должен отслеживать.Вот код:
Модульный тест, который завершается неудачей:
class AuctionTest < ActiveSupport::TestCase
test "are monitored when created" do
auction = Auction.new(
:name => "A TV",
:markdown => "A large TV",
:starting_bid => 0.01,
:bid_increment => 0.01,
:starts_at => Time.now(),
:ends_at => Time.now() + 5.seconds,
:active => true
)
auction.save
Bid.place(@current_user, auction)
sleep(10) #when bids are placed, time is added to the end of the auction so wait
assert auction.won?
assert_equal @current_user.id, auction.winner_id
end
end
Рабочий кодекс:
class AuctionsWorker < Workling::Base
def monitor(options)
active = true
ends_at = options[:original_ends_at]
while active
auction = Auction.find(options[:auction_id]) #this is the record that cannot be found
if auction.won?
active = false
winner = User.find(auction.high_bidder).id
auction.update_attribute(:winner_id, winner)
else
until Time.now() >= ends_at
sleep(1)
end
end
end
end
end
Код, вызывающий работника:
class Auction < ActiveRecord::Base
def after_create
AuctionsWorker.asynch_monitor(:auction_id => self.id, :original_ends_at => self.ends_at) if self.active?
end
end
Каждый раз, когда я запускаю тест, я получаю сообщение об ошибке, сообщающее мне, что аукцион, предоставленный работнику, не может быть найден.
У кого-нибудь есть какие-нибудь идеи?Я использую rails 2.3.5, sqlite3 и последнюю версию Starling, Workling и все другие связанные с ними драгоценные камни на Mac OSX 10.6.2 Macbook Pro, если это поможет.
Спасибо вам за весь вклад.
Решение
Вы должны быть отвергнуты за создание аукциона в стиле "свупо", и я чувствую себя грязным из-за того, что помогаю вам.
after_create() Вызывается после Base.save для новых объектов, которые еще не были сохранены (записи не существует)
так что after_create - это немного неправильное название - запись на самом деле еще не создана.
http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002142
Вы могли бы добавить свое собственное поле id и заставить рабочий процесс искать этот id в базе данных, отключаясь на несколько секунд каждый раз, когда он его не находит (до некоторого заданного предела сбоев).
В качестве альтернативы - вы могли бы попробовать один из нескольких плагинов after_commit, которые есть на github и которые вызываются после обновления базы данных.
Вот один из них: