feedupdater 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,2 +1,5 @@
1
+ == FeedUpdater 0.2.0
2
+ * multithreaded
3
+ * unchanged feeds will no longer call on_update
1
4
  == FeedUpdater 0.1.0
2
5
  * initial version
@@ -5,8 +5,15 @@ start_delay: false
5
5
  # See the documentation for details.
6
6
  load_script: example/custom_updater.rb
7
7
 
8
+ # Keep this set to 1 unless you're certain you need to set it higher.
9
+ # Never set it higher than 1 if you're on a shared server.
10
+ threads: 5
11
+
8
12
  # This is the path to store the pid files.
9
13
  pid_file_path: config
10
14
 
11
15
  # This is the path to store the log files.
12
16
  log_file_path: log
17
+
18
+ # Log level
19
+ log_level: 0
@@ -1,7 +1,7 @@
1
1
  module FeedTools
2
2
  module FEED_UPDATER_VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
4
+ MINOR = 2
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
data/lib/feed_updater.rb CHANGED
@@ -55,6 +55,41 @@ if !defined?(FeedTools::FEED_TOOLS_VERSION)
55
55
  end
56
56
 
57
57
  require 'benchmark'
58
+ require 'thread'
59
+ require 'logger'
60
+
61
+ class FeedUpdaterLogger < Logger
62
+ attr_accessor :prefix
63
+
64
+ alias_method :old_log, :log
65
+ def log(level, message)
66
+ if defined?(@prefix) && @prefix != nil
67
+ self.old_log(level, self.prefix + message)
68
+ else
69
+ self.old_log(level, message)
70
+ end
71
+ end
72
+
73
+ def debug(message)
74
+ self.log(0, message)
75
+ end
76
+
77
+ def info(message)
78
+ self.log(1, message)
79
+ end
80
+
81
+ def warn(message)
82
+ self.log(2, message)
83
+ end
84
+
85
+ def error(message)
86
+ self.log(3, message)
87
+ end
88
+
89
+ def fatal(message)
90
+ self.log(4, message)
91
+ end
92
+ end
58
93
 
59
94
  module FeedTools
60
95
  # A simple daemon for scheduled updating of feeds.
@@ -127,7 +162,11 @@ module FeedTools
127
162
  # Returns the logger object.
128
163
  def logger()
129
164
  if !defined?(@logger) || @logger.nil?
130
- @logger = Logger.new(self.log_file)
165
+ @logger = FeedUpdaterLogger.new(self.log_file)
166
+ @logger.level = self.updater_options[:log_level]
167
+ @logger.datetime_format = nil
168
+ @logger.progname = nil
169
+ @logger.prefix = "FeedUpdater".ljust(20)
131
170
  end
132
171
  return @logger
133
172
  end
@@ -139,7 +178,11 @@ module FeedTools
139
178
  self.logger.close()
140
179
  rescue IOError
141
180
  end
142
- @logger = Logger.new(self.log_file)
181
+ @logger = FeedUpdaterLogger.new(self.log_file)
182
+ @logger.level = self.updater_options[:log_level]
183
+ @logger.datetime_format = nil
184
+ @logger.progname = nil
185
+ @logger.prefix = "FeedUpdater".ljust(20)
143
186
  end
144
187
 
145
188
  # Returns a list of feeds to be updated.
@@ -174,7 +217,9 @@ module FeedTools
174
217
  def updater_options()
175
218
  if !defined?(@updater_options) || @updater_options.nil?
176
219
  @updater_options = {
177
- :start_delay => true
220
+ :start_delay => true,
221
+ :thread => 1,
222
+ :log_level => 0
178
223
  }
179
224
  end
180
225
  return @updater_options
@@ -234,6 +279,7 @@ module FeedTools
234
279
 
235
280
  # Starts the daemon.
236
281
  def start()
282
+ self.logger.prefix = "FeedUpdater".ljust(20)
237
283
  if !defined?(@@on_update) || @@on_update.nil?
238
284
  raise "No on_update handler block given."
239
285
  end
@@ -241,6 +287,9 @@ module FeedTools
241
287
  puts "FeedUpdater is already running."
242
288
  return self.pid
243
289
  end
290
+ if defined?(ActiveRecord)
291
+ ActiveRecord::Base.allow_concurrency = true
292
+ end
244
293
 
245
294
  @initial_directory = File.expand_path(".")
246
295
 
@@ -280,9 +329,13 @@ module FeedTools
280
329
  self.update_feeds()
281
330
  end
282
331
  self.logger.info(
283
- "#{@feed_href_list.size} feeds updated " +
332
+ "#{@feed_href_list.size} feed(s) updated " +
284
333
  "in #{result.real.round} seconds.")
285
- ObjectSpace.garbage_collect
334
+ if !defined?(@feed_href_list_override) ||
335
+ !@feed_href_list_override
336
+ @feed_href_list = nil
337
+ end
338
+ ObjectSpace.garbage_collect()
286
339
  sleepy_time = 1.hour - result.real.round
287
340
  if sleepy_time > 0
288
341
  self.logger.info(
@@ -304,11 +357,16 @@ module FeedTools
304
357
  else
305
358
  @application.start()
306
359
  end
360
+ self.logger.prefix = nil
361
+ self.logger.level = 0
307
362
  self.logger.info("-" * 79)
308
363
  self.logger.info("Daemon started, " +
309
364
  "FeedUpdater #{FeedTools::FEED_UPDATER_VERSION::STRING} / " +
310
365
  "FeedTools #{FeedTools::FEED_TOOLS_VERSION::STRING}")
311
366
  self.logger.info(" @ #{Time.now.utc.to_s}")
367
+ self.logger.info("-" * 79)
368
+ self.logger.level = self.updater_options[:log_level]
369
+ self.logger.prefix = "FeedUpdater".ljust(20)
312
370
  @status = :running
313
371
  return self.pid
314
372
  end
@@ -340,7 +398,10 @@ module FeedTools
340
398
  end
341
399
  rescue Exception
342
400
  end
401
+ self.logger.prefix = "FeedUpdater".ljust(20)
402
+ self.logger.level = 0
343
403
  self.logger.info("Daemon stopped.")
404
+ self.logger.level = self.updater_options[:log_level]
344
405
  @status = :stopped
345
406
  return nil if self.application.nil?
346
407
  begin
@@ -358,40 +419,170 @@ module FeedTools
358
419
 
359
420
  # Updates all of the feeds.
360
421
  def update_feeds()
422
+ self.logger.prefix = "FeedUpdater".ljust(20)
423
+ ObjectSpace.garbage_collect()
361
424
  if defined?(@feed_href_list_override) && @feed_href_list_override
362
425
  self.feed_href_list()
363
426
  else
427
+ self.logger.info("Loading default feed list...")
364
428
  @feed_href_list =
365
- FeedTools.feed_cache.find(:all).collect do |cache_object|
366
- cache_object.href
429
+ (FeedTools.feed_cache.find(:all).collect do |cache_object|
430
+ cache_object.href
431
+ end)
432
+ end
433
+ self.logger.info("Updating #{@feed_href_list.size} feed(s)...")
434
+ ObjectSpace.garbage_collect()
435
+
436
+ threads = []
437
+ thread_slices = []
438
+ thread_slice_size =
439
+ (@feed_href_list.size / self.updater_options[:threads])
440
+
441
+ for i in 0...self.updater_options[:threads]
442
+ if i != self.updater_options[:threads] - 1
443
+ thread_slices << @feed_href_list[
444
+ (i * thread_slice_size)...((i + 1) * thread_slice_size)]
445
+ else
446
+ thread_slices << @feed_href_list[
447
+ (i * thread_slice_size)..-1]
367
448
  end
368
449
  end
369
- self.logger.info("Updating #{@feed_href_list.size} feeds...")
370
- for href in @feed_href_list
371
- begin
372
- begin
373
- feed = nil
374
- feed_load_benchmark = Benchmark.measure do
375
- feed = FeedTools::Feed.open(href)
376
- end
377
- unless @@on_update.nil?
378
- self.cloaker(&(@@on_update)).bind(self).call(
379
- feed, feed_load_benchmark.real)
380
- end
381
- rescue Exception => error
382
- if @@on_error != nil
383
- self.cloaker(&(@@on_error)).bind(self).call(href, error)
384
- else
385
- self.logger.info("Error updating '#{href}':")
450
+ ObjectSpace.garbage_collect()
451
+
452
+ begin_updating = false
453
+ self.logger.info(
454
+ "Starting up #{self.updater_options[:threads]} thread(s)...")
455
+
456
+ mutex = Mutex.new
457
+ for i in 0...self.updater_options[:threads]
458
+ updater_thread = Thread.new do
459
+ self.logger.level = self.updater_options[:log_level]
460
+ self.logger.datetime_format = "%s"
461
+ self.logger.progname = "FeedUpdater".ljust(20)
462
+
463
+ while !Thread.current.respond_to?(:thread_id) &&
464
+ begin_updating == false
465
+ Thread.pass
466
+ end
467
+ mutex.synchronize do
468
+ self.logger.prefix = "Thread #{Thread.current.thread_id} ".ljust(20)
469
+ self.logger.info("Thread started.")
470
+
471
+ begin
472
+ FeedTools.feed_cache.initialize_cache()
473
+ if !FeedTools.feed_cache.set_up_correctly?
474
+ self.logger.info("Problem with cache connection...")
475
+ end
476
+ rescue Exception => error
386
477
  self.logger.info(error)
387
478
  end
479
+
480
+ self.logger.info(
481
+ "Thread ##{Thread.current.thread_id} handling " +
482
+ "#{thread_slices[Thread.current.thread_id].size} feeds...")
388
483
  end
389
- rescue Exception => error
390
- self.logger.info("Critical unhandled error.")
391
- self.logger.info("Error updating '#{href}':")
392
- self.logger.info(error)
484
+
485
+ ObjectSpace.garbage_collect()
486
+ Thread.pass
487
+ href_list = thread_slices[Thread.current.thread_id]
488
+
489
+ for i in 0...href_list.size
490
+ href = nil
491
+ progress = nil
492
+ mutex.synchronize do
493
+ href = href_list[i]
494
+ Thread.current.progress =
495
+ (href_list.index(href).to_f / href_list.size.to_f) * 100
496
+ progress = sprintf("%.2f", Thread.current.progress)
497
+ end
498
+ begin
499
+ begin
500
+ feed = nil
501
+ feed_load_benchmark = Benchmark.measure do
502
+ feed = FeedTools::Feed.open(href)
503
+ end
504
+ Thread.pass
505
+ if feed.live?
506
+ unless @@on_update.nil?
507
+ mutex.synchronize do
508
+ progress = sprintf("%.2f", Thread.current.progress)
509
+ self.logger.prefix = ("Thread #{Thread.current.thread_id} " +
510
+ "(#{progress}%)"
511
+ ).ljust(20)
512
+ self.cloaker(&(@@on_update)).bind(self).call(
513
+ feed, feed_load_benchmark.real)
514
+ end
515
+ end
516
+ else
517
+ mutex.synchronize do
518
+ progress = sprintf("%.2f", Thread.current.progress)
519
+ self.logger.prefix = ("Thread #{Thread.current.thread_id} " +
520
+ "(#{progress}%)"
521
+ ).ljust(20)
522
+ self.logger.info(
523
+ "'#{href}' unchanged, skipping.")
524
+ end
525
+ end
526
+ rescue Exception => error
527
+ mutex.synchronize do
528
+ progress = sprintf("%.2f", Thread.current.progress)
529
+ self.logger.prefix = ("Thread #{Thread.current.thread_id} " +
530
+ "(#{progress}%)"
531
+ ).ljust(20)
532
+ if @@on_error != nil
533
+ self.cloaker(&(@@on_error)).bind(self).call(href, error)
534
+ else
535
+ self.logger.error("Error updating '#{href}':")
536
+ self.logger.error(error.class.name + ": " + error.message)
537
+ self.logger.error(error.class.backtrace)
538
+ end
539
+ end
540
+ end
541
+ rescue Exception => error
542
+ mutex.synchronize do
543
+ progress = sprintf("%.2f", Thread.current.progress)
544
+ self.logger.prefix = ("Thread #{Thread.current.thread_id} " +
545
+ "(#{progress}%)"
546
+ ).ljust(20)
547
+ self.logger.fatal("Critical unhandled error.")
548
+ self.logger.fatal("Error updating '#{href}':")
549
+ self.logger.fatal(error.class.name + ": " + error.message)
550
+ self.logger.fatal(error.class.backtrace)
551
+ end
552
+ end
553
+ ObjectSpace.garbage_collect()
554
+ Thread.pass
555
+ end
556
+ end
557
+ threads << updater_thread
558
+ class <<updater_thread
559
+ attr_accessor :thread_id
560
+ attr_accessor :progress
561
+ end
562
+ updater_thread.thread_id = i
563
+ end
564
+ mutex.synchronize do
565
+ self.logger.prefix = "FeedUpdater".ljust(20)
566
+ self.logger.info(
567
+ "#{threads.size} thread(s) successfully started...")
568
+ begin_updating = true
569
+ end
570
+ Thread.pass
571
+
572
+ ObjectSpace.garbage_collect()
573
+ Thread.pass
574
+ for i in 0...threads.size
575
+ mutex.synchronize do
576
+ self.logger.prefix = "FeedUpdater".ljust(20)
577
+ self.logger.info(
578
+ "Joining on thread #{threads[i].thread_id}...")
393
579
  end
580
+ threads[i].join
394
581
  end
582
+ self.logger.prefix = "FeedUpdater".ljust(20)
583
+ ObjectSpace.garbage_collect()
584
+
585
+ self.logger.progname = nil
395
586
  unless @@on_complete.nil?
396
587
  self.cloaker(&(@@on_complete)).bind(self).call(@feed_href_list)
397
588
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: feedupdater
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2006-04-13 00:00:00 -07:00
6
+ version: 0.2.0
7
+ date: 2006-04-17 00:00:00 -07:00
8
8
  summary: Automatic feed updater daemon.
9
9
  require_paths:
10
10
  - lib
@@ -32,7 +32,6 @@ files:
32
32
  - bin
33
33
  - CHANGELOG
34
34
  - config
35
- - doc
36
35
  - example
37
36
  - lib
38
37
  - log
@@ -55,7 +54,6 @@ files:
55
54
  - lib/feed_updater/vendor/daemons/pid.rb
56
55
  - lib/feed_updater/vendor/daemons/pidfile.rb
57
56
  - lib/feed_updater/vendor/daemons/pidmem.rb
58
- - config/feed_updater.pid
59
57
  - config/feed_updater.yml
60
58
  - example/custom_updater.rb
61
59
  test_files: []
@@ -1 +0,0 @@
1
- 617