Yeah, this is fun!
So I''m trying to check a bunch of websites to see if they''ve
been updated
since the last time I check them. I''m using threads and SizedQueue to
grab
sets of "feed" objects out of the database, then send them off to be
downloaded and compared to existing records.
I sometimes get this error, which I don''t understand:
[2005-11-04 13:10:15] ERROR SystemExit:
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/base
.rb:1412:in `select''
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/base
.rb:1412:in `method_missing'': undefined method `accounts'' for
#<Feed:0x25d3af8> (NoMethodError)
I don''t really even know if this is a sane approach so any suggestions
are
welcome. Since I am retrieving the feed objects in one thread, then
modifying them and saving them in a different thread, do I need to so
anything special, like pre-fetch the accounts collection somehow?
Below is the code that''s being used to produce the problems:
<code>
# method run by controller
def check_all_feeds_and_create_tells
fill_feed_queue
sleep(1.minute)
checkers = (1..3).map do |i|
process_feed_chunk
end
end
private
def fill_feed_queue
last_at = 0
@queue = SizedQueue.new(10) # with a capacity for 10
# we do the queue filling in a single thread that runs until no more
items are left to add
Thread.new do
loop do
logger.debug("Fetching next block of feeds: limit
#{FEED_FETCH_LIMIT}, offset = #{last_at}")
feeds = Feed.find(:all, :limit => FEED_FETCH_LIMIT, :offset =>
last_at)
break if feeds == nil || feeds.length == 0
last_at += feeds.length
# add each feed found to the queue
feeds.each do |feed|
feed.accounts # load the accounts so they are available later as
part of this feed object (othwerwise accounts throws NoSuchMethod )
@queue << feed
end
sleep(10) # 10 second break
end #loop
end # thread.new
end # def
def process_feed_chunk
Thread.new do
loop do
feed = @queue.pop
logger.debug("Processing feed: #{feed}")
begin
item = get_first_item feed.url
rescue Exception
logger.warn("The feed #{feed.url} could not be retrieved:
#{$!}")
next
end
if ( feed.signature != item[:title] ) # if the feed appears
to have been updated
feed.signature = item[:title] # then save the new signature
feed.save
feed.accounts.each do |account| #### THE ERROR IS PRODUCED HERE
tell = Tell.new
tell.message = "[#{item[:channel_title]} ( #{item[:link]} ):
#{item[:title]} ] \n #{item[:description]} \n" +
"--
http://localhost:3000/accounts/#{account.id}"
account.tells << tell
end
end # if feed.sig
end # loop do
end # Thread.new
end # def
</code>