diff --git a/.gitignore b/.gitignore index a1180a1..a24fabb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ coverage rdoc doc pkg -tmp \ No newline at end of file +tmp +*.gem +.bundle diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..64b6509 --- /dev/null +++ b/Gemfile @@ -0,0 +1,29 @@ +source 'http://rubygems.org' + +group :active_record do + gem 'activerecord', '>= 2.3.5' +end + +group :data_mapper do + gem 'dm-core', '>= 0.10.2' +end + +group :mongo_mapper do + gem 'mongo_mapper', '>= 0.7.0' +end + +group :sequel do + gem 'sequel', '>= 3.8.0' +end + +group :mongoid do + gem 'mongoid' + gem 'builder' + gem 'tzinfo' +end + +group :test do + gem 'rspec', '1.3.0' +end + +gem 'yard', '>= 0.5.2' diff --git a/README.textile b/README.textile index 5e73498..f01d2ef 100644 --- a/README.textile +++ b/README.textile @@ -1,16 +1,18 @@ h1. Navvy -Navvy is a simple Ruby background job processor inspired by "delayed_job":http://github.com/tobi/delayed_job, but aiming for database agnosticism. Currently Navvy supports ActiveRecord, MongoMapper, Sequel and DataMapper but it's extremely easy to write an adapter for your favorite ORM. Besides plain Ruby (1.8 & 1.9) it completely supports Rails Edge. +Navvy is a simple Ruby background job processor inspired by "delayed_job":http://github.com/tobi/delayed_job, but aiming for database agnosticism. Currently Navvy supports ActiveRecord, MongoMapper, Sequel, DataMapper and Mongoid but it's extremely easy to write an adapter for your favorite ORM. + +Navvy doesn't depend on Rails, it's a pure Ruby library. There are generators for Rails 2 and Rails 3, though. ??“Navvy is a shorter form of navigator (UK) or navigational engineer (USA) and is particularly applied to describe the manual labourers working on major civil engineering projects. The term was coined in the late 18th century in Britain when numerous canals were being built, which were also sometimes known as "navigations". Canal navvies typically worked with shovels, pickaxes and barrows.”?? - "Wikipedia":http://en.wikipedia.org/wiki/Navvy h2. Using Navvy -There are some "Installation Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/installation (even for "Rails 3":http://wiki.github.com/jeffkreeftmeijer/navvy/installation-on-rails-edge) and a "Getting Started Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/getting-started to put you on the right track. Any questions? Don't hesitate to "ask":http://github.com/inbox/new/jeffkreeftmeijer. +Check out the "Installation Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/installation and the "Getting Started Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/getting-started to get up and running. If you have any questions or problems, don't hesitate to "ask":http://github.com/inbox/new/jeffkreeftmeijer. h2. Contributing -Found any issues? Have a great idea? Want to help? Great! Create an issue "issue":http://github.com/jeffkreeftmeijer/navvy/issues for it, or even better; "fork the project":http://github.com/jeffkreeftmeijer/navvy/fork. Pull requests are always welcome. :) +Found an issue? Have a great idea? Want to help? Great! Create an issue "issue":http://github.com/jeffkreeftmeijer/navvy/issues for it, "ask":http://github.com/inbox/new/jeffkreeftmeijer, or even better; fork the project and fix the problem yourself. Pull requests are always welcome. :) h2. License diff --git a/Rakefile b/Rakefile index d87feeb..b564c38 100644 --- a/Rakefile +++ b/Rakefile @@ -1,50 +1,19 @@ -require 'rubygems' require 'rake' - -begin - require 'jeweler' - Jeweler::Tasks.new do |gem| - gem.name = "navvy" - gem.summary = %Q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.} - gem.description = %Q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.} - gem.email = "jeff@kreeftmeijer.nl" - gem.homepage = "http://github.com/jeffkreeftmeijer/navvy" - gem.authors = ["Jeff Kreeftmeijer"] - - gem.add_development_dependency "rspec", ">= 1.2.9" - gem.add_development_dependency "yard", ">= 0.5.2" - gem.add_development_dependency "sequel", ">= 3.8.0" - gem.add_development_dependency "sqlite3-ruby", ">= 1.2.5" - gem.add_dependency "daemons", ">= 1.0.10" - end - Jeweler::GemcutterTasks.new -rescue LoadError - puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" -end - require 'spec/rake/spectask' +adapters = Dir[File.dirname(__FILE__) + '/lib/navvy/job/*.rb'].map{|file| File.basename(file, '.rb') } + task :spec do - ['spec:active_record', 'spec:mongo_mapper', 'spec:sequel', 'spec:data_mapper'].each do |spec| + adapters.map{|adapter| "spec:#{adapter}"}.each do |spec| Rake::Task[spec].invoke end end namespace :spec do - Spec::Rake::SpecTask.new(:active_record) do |spec| - spec.spec_files = FileList['spec/setup/active_record.rb', 'spec/*_spec.rb'] - end - - Spec::Rake::SpecTask.new(:mongo_mapper) do |spec| - spec.spec_files = FileList['spec/setup/mongo_mapper.rb', 'spec/*_spec.rb'] - end - - Spec::Rake::SpecTask.new(:sequel) do |spec| - spec.spec_files = FileList['spec/setup/sequel.rb', 'spec/*_spec.rb'] - end - - Spec::Rake::SpecTask.new(:data_mapper) do |spec| - spec.spec_files = FileList['spec/setup/data_mapper.rb', 'spec/*_spec.rb'] + adapters.each do |adapter| + Spec::Rake::SpecTask.new(adapter) do |spec| + spec.spec_files = FileList["spec/setup/#{adapter}.rb", 'spec/*_spec.rb'] + end end end @@ -54,7 +23,6 @@ Spec::Rake::SpecTask.new(:rcov) do |spec| spec.rcov = true end -task :spec => :check_dependencies task :default => :spec begin diff --git a/VERSION b/VERSION deleted file mode 100644 index 3a4036f..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.2.5 diff --git a/generators/navvy/navvy_generator.rb b/generators/navvy/navvy_generator.rb index 71e314d..863a7ad 100644 --- a/generators/navvy/navvy_generator.rb +++ b/generators/navvy/navvy_generator.rb @@ -1,14 +1,19 @@ class NavvyGenerator < Rails::Generator::Base + default_options :orm => 'active_record' + def manifest record do |m| - options = { - :migration_file_name => 'create_jobs' - } - m.migration_template 'migration.rb', 'db/migrate', options - m.file 'script', 'script/navvy', :chmod => 0755 + m.migration_template "#{options[:orm]}_migration.rb", 'db/migrate', {:migration_file_name => 'create_jobs'} end end + def add_options!(opt) + opt.separator '' + opt.separator 'Options:' + opt.on('--active_record', 'Generate a migration file for ActiveRecord. (default)') { options[:orm] = 'active_record' } + opt.on('--sequel', 'Generate a migration file for Sequel.') { options[:orm] = 'sequel' } + end + def banner "Usage: #{$0} #{spec.name}" end diff --git a/generators/navvy/templates/migration.rb b/generators/navvy/templates/active_record_migration.rb similarity index 100% rename from generators/navvy/templates/migration.rb rename to generators/navvy/templates/active_record_migration.rb diff --git a/generators/navvy/templates/script b/generators/navvy/templates/script deleted file mode 100644 index 7ffbbb4..0000000 --- a/generators/navvy/templates/script +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby - -require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) -Navvy::Worker.daemonize diff --git a/generators/navvy/templates/sequel_migration.rb b/generators/navvy/templates/sequel_migration.rb new file mode 100644 index 0000000..be798b5 --- /dev/null +++ b/generators/navvy/templates/sequel_migration.rb @@ -0,0 +1,23 @@ +Sequel.migration do + up do + create_table(:jobs) do + primary_key :id, :type => Integer + String :object + String :method_name + String :arguments, :text => true + Integer :priority, :default => 0 + String :return + String :exception + Integer :parent_id + DateTime :created_at + DateTime :run_at + DateTime :started_at + DateTime :completed_at + DateTime :failed_at + end + end + + down do + drop_table(:jobs) + end +end diff --git a/lib/generators/navvy_generator.rb b/lib/generators/navvy_generator.rb index 82cfd49..26b4a54 100644 --- a/lib/generators/navvy_generator.rb +++ b/lib/generators/navvy_generator.rb @@ -2,21 +2,27 @@ class NavvyGenerator < Rails::Generators::Base include Rails::Generators::Migration + class_option :active_record, + :desc => 'Generate a migration file for ActiveRecord. (default)', + :type => 'boolean' + + class_option :sequel, + :desc => 'Generate a migration file for Sequel.', + :type => 'boolean' + def self.source_root File.join(File.dirname(__FILE__), '..', '..', 'generators', 'navvy', 'templates') end def install_navvy migration_template( - 'migration.rb', + "#{orm}_migration.rb", 'db/migrate/create_jobs.rb' ) + end - copy_file( - 'script', - 'script/navvy', - :chmod => 0755 - ) + def orm + options[:sequel] ? 'sequel' : 'active_record' end protected diff --git a/lib/navvy.rb b/lib/navvy.rb index 0fecb6b..e2c432d 100644 --- a/lib/navvy.rb +++ b/lib/navvy.rb @@ -1,16 +1,20 @@ require File.expand_path(File.dirname(__FILE__) + '/navvy/worker') -require File.expand_path(File.dirname(__FILE__) + '/navvy/log') +require File.expand_path(File.dirname(__FILE__) + '/navvy/logger') require File.expand_path(File.dirname(__FILE__) + '/navvy/configuration') module Navvy class << self attr_writer :configuration end - + + def self.logger + @logger || Navvy.configuration.logger + end + def self.configuration @configuration ||= Configuration.new end - + def self.configure yield(self.configuration) end diff --git a/lib/navvy/configuration.rb b/lib/navvy/configuration.rb index 3cb85fb..2ad92e5 100644 --- a/lib/navvy/configuration.rb +++ b/lib/navvy/configuration.rb @@ -1,15 +1,13 @@ module Navvy class Configuration - attr_accessor :job_limit, :keep_jobs, :logger, :quiet, :sleep_time, - :max_attempts - + attr_accessor :job_limit, :keep_jobs, :logger, :sleep_time, :max_attempts + def initialize @job_limit = 100 @keep_jobs = false - @logger = nil - @quiet = false + @logger = Navvy::Logger.new @sleep_time = 5 @max_attempts = 25 end end -end \ No newline at end of file +end diff --git a/lib/navvy/job.rb b/lib/navvy/job.rb index c1e317b..489122b 100755 --- a/lib/navvy/job.rb +++ b/lib/navvy/job.rb @@ -152,14 +152,14 @@ def status alias_method :completed?, :completed_at? alias_method :failed?, :failed_at? - + private - + ## # Turn a constant with potential namespacing into an object # # @return [Class] class - + def constantize(str) names = str.split('::') names.shift if names.empty? || names.first.empty? diff --git a/lib/navvy/job/active_record.rb b/lib/navvy/job/active_record.rb index f8af9cd..59ff430 100644 --- a/lib/navvy/job/active_record.rb +++ b/lib/navvy/job/active_record.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'active_record' module Navvy diff --git a/lib/navvy/job/data_mapper.rb b/lib/navvy/job/data_mapper.rb index de43b66..625d0a1 100644 --- a/lib/navvy/job/data_mapper.rb +++ b/lib/navvy/job/data_mapper.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'dm-core' module Navvy diff --git a/lib/navvy/job/mongo_mapper.rb b/lib/navvy/job/mongo_mapper.rb index ca40369..bd3ae66 100644 --- a/lib/navvy/job/mongo_mapper.rb +++ b/lib/navvy/job/mongo_mapper.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'mongo_mapper' module Navvy diff --git a/lib/navvy/job/mongoid.rb b/lib/navvy/job/mongoid.rb new file mode 100644 index 0000000..e23c8ca --- /dev/null +++ b/lib/navvy/job/mongoid.rb @@ -0,0 +1,139 @@ +require 'mongoid' + +module Navvy + class Job + include Mongoid::Document + include Mongoid::Timestamps + + field :object, :type => String + field :method_name, :type => String + field :arguments, :type => String + field :priority, :type => Integer, :default => 0 + field :return, :type => String + field :exception, :type => String + field :parent_id, :type => String + field :created_at, :type => Time + field :run_at, :type => Time + field :started_at, :type => Time + field :completed_at, :type => Time + field :failed_at, :type => Time + + index [[:priority, Mongo::DESCENDING]] + index [[:created_at, Mongo::ASCENDING]] + + ## + # Add a job to the job queue. + # + # @param [Object] object the object you want to run a method from + # @param [Symbol, String] method_name the name of the method you want to + # run + # @param [*] arguments optional arguments you want to pass to the method + # + # @return [true, false] + + def self.enqueue(object, method_name, *args) + options = {} + if args.last.is_a?(Hash) + options = args.last.delete(:job_options) || {} + args.pop if args.last.empty? + end + + create( + :object => object.to_s, + :method_name => method_name.to_sym, + :arguments => args.to_yaml, + :priority => options[:priority] || 0, + :parent_id => options[:parent_id], + :run_at => options[:run_at] || Time.now + ) + end + + ## + # Find the next available jobs in the queue. This will not include failed + # jobs (where :failed_at is not nil) and jobs that should run in the future + # (where :run_at is greater than the current time). + # + # @param [Integer] limit the limit of jobs to be fetched. Defaults to + # Navvy::Job.limit + # + # @return [array, nil] the next available jobs in an array or nil if no + # jobs were found. + + def self.next(limit = self.limit) + where(:failed_at => nil). + where(:completed_at => nil). + where(:run_at.lte => Time.now). + order_by([[:priority, :desc], [:created_at, :asc]]). + limit(limit).to_a + end + + ## + # Clean up jobs that we don't need to keep anymore. If Navvy::Job.keep is + # false it'll delete every completed job, if it's a timestamp it'll only + # delete completed jobs that have passed their keeptime. + # + # @return [true, false] delete_all the result of the delete_all call + + def self.cleanup + if keep.is_a? Fixnum + destroy_all(:conditions => { :completed_at.lte => keep.ago }) + else + destroy_all(:conditions => { :completed_at.ne => nil }) unless keep? + end + end + + ## + # Mark the job as started. Will set started_at to the current time. + # + # @return [true, false] update_attributes the result of the + # update_attributes call + + def started + update_attributes(:started_at => Time.now) + end + + ## + # Mark the job as completed. Will set completed_at to the current time and + # optionally add the return value if provided. + # + # @param [String] return_value the return value you want to store. + # + # @return [true, false] update_attributes the result of the + # update_attributes call + + def completed(return_value = nil) + update_attributes(:completed_at => Time.now, :return => return_value) + end + + ## + # Mark the job as failed. Will set failed_at to the current time and + # optionally add the exception message if provided. Also, it will retry + # the job unless max_attempts has been reached. + # + # @param [String] exception the exception message you want to store. + # + # @return [true, false] update_attributes the result of the + # update_attributes call + + def failed(message = nil) + self.retry unless times_failed >= self.class.max_attempts + update_attributes(:failed_at => Time.now, :exception => message) + end + + ## + # Check how many times the job has failed. Will try to find jobs with a + # parent_id that's the same as self.id and count them + # + # @return [Integer] count the amount of times the job has failed + + def times_failed + i = parent_id || id + self.class. + where(:failed_at.ne => nil). + where("this._id == '#{i}' || this.parent_id == '#{i}'"). + count + end + end +end + +require File.expand_path(File.dirname(__FILE__) + '/../job') diff --git a/lib/navvy/job/sequel.rb b/lib/navvy/job/sequel.rb index 5a888d5..eef8c79 100644 --- a/lib/navvy/job/sequel.rb +++ b/lib/navvy/job/sequel.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'sequel' require 'yaml' @@ -48,7 +47,7 @@ def self.enqueue(object, method_name, *args) def self.next(limit = self.limit) filter( (:run_at <= Time.now), - {:failed_at => nil, + {:failed_at => nil, :completed_at => nil} ).order(:priority.desc, :created_at).first(limit) end diff --git a/lib/navvy/log.rb b/lib/navvy/log.rb deleted file mode 100644 index 5bc4533..0000000 --- a/lib/navvy/log.rb +++ /dev/null @@ -1,74 +0,0 @@ -module Navvy - class Log - class << self - attr_writer :logger - attr_accessor :quiet - end - - class LoggerNotFound < StandardError; end - - ## - # Default logger - # - # @return [Symbol, nil] logger - - def self.logger - @logger || Navvy.configuration.logger - end - - ## - # Be quiet? - # - # @return [true, false] quiet - - def self.quiet - @quiet || Navvy.configuration.quiet - end - - ## - # Pass a log to the logger. It will check if self.logger is an array. If it - # is, it'll loop through it and log to every logger. If it's not, it'll - # just log once. - # - # @param [String] message the message you want to log - # @param [Integer] color an optional color code to use in the terminal - # output - - def self.info(message, color = nil) - if logger.is_a? Array - logger.each do |logger| - write(logger, message, color) - end - else - write(logger, message, color) - end - end - - ## - # Actually write the log to the logger. It'll check self.logger and use - # that to define a logger - # - # @param [Symbol] logger the logger you want to use - # @param [String] message the message you want to log - # @param [Integer] color an optional color code to use in the terminal - # output - - def self.write(logger, message, color = nil) - puts "\e[#{color}m#{message}\e[0m" unless quiet - case logger - when :justlogging - raise( - LoggerNotFound, - 'JustLogging could not be found. No logs were created.' - ) unless defined? Justlogging.log - Justlogging.log(message) - when :rails - raise( - LoggerNotFound, - 'Rails.logger could not be found. No logs were created.' - ) unless defined? Rails.logger.info - Rails.logger.info(message) - end - end - end -end diff --git a/lib/navvy/logger.rb b/lib/navvy/logger.rb new file mode 100644 index 0000000..ac7f0ff --- /dev/null +++ b/lib/navvy/logger.rb @@ -0,0 +1,38 @@ +require 'logger' + +module Navvy + class Logger < Logger + ## + # Create a new logger. Works like Logger from Ruby's standard library, but + # defaults to STDOUT instead of failing. You can pass a filename to log to. + # + # @param [String] logdev a filename to log to, defaults to STDOUT + # + # @example + # logger = Navvy::Logger.new + # logger = Navvy::Logger.new('~/file.log') + + def initialize(logdev = STDOUT) + super logdev + end + + ## + # Send colored logs to the logger. Will only colorize output sent to + # STDOUT and will call the regular info method when writing to file. + # + # @param [String] message the message you want to log + # @param [String] color the color code you want to use to color your + # message + # + # @example + # logger = Navvy::Logger.new + # logger.colorized_info "I'm green!", 32 + + def colorized_info(message, color) + unless @logdev.filename + return info("\e[#{color}m#{message}\e[0m") + end + info(message) + end + end +end diff --git a/lib/navvy/tasks.rb b/lib/navvy/tasks.rb index e706216..cbf558e 100644 --- a/lib/navvy/tasks.rb +++ b/lib/navvy/tasks.rb @@ -1,11 +1,11 @@ task :environment - + namespace :navvy do desc "Clear the Navvy queue." task :clear => :environment do Navvy::Job.delete_all end - + desc "Start a Navvy worker." task :work => :environment do Navvy::Worker.start diff --git a/lib/navvy/worker.rb b/lib/navvy/worker.rb index b98f04b..1249cd9 100644 --- a/lib/navvy/worker.rb +++ b/lib/navvy/worker.rb @@ -1,6 +1,3 @@ -require 'rubygems' -require 'daemons' - module Navvy class Worker class << self @@ -20,15 +17,15 @@ def self.sleep_time # Start the worker. def self.start - Navvy::Log.info '*** Starting ***' - trap('TERM') { Navvy::Log.info '*** Exiting ***'; $exit = true } - trap('INT') { Navvy::Log.info '*** Exiting ***'; $exit = true } + Navvy.logger.info '*** Starting ***' + trap('TERM') { Navvy.logger.info '*** Exiting ***'; $exit = true } + trap('INT') { Navvy.logger.info '*** Exiting ***'; $exit = true } loop do fetch_and_run_jobs if $exit - Navvy::Log.info '*** Cleaning up ***' + Navvy.logger.info '*** Cleaning up ***' Navvy::Job.cleanup break end @@ -42,41 +39,12 @@ def self.start def self.fetch_and_run_jobs Job.next.each do |job| result = job.run - Navvy::Log.info( + Navvy.logger.colorized_info( "* #{job.object.to_s}.#{job.method_name}" << "(#{job.args.join(', ')}) => #{(job.exception || result).to_s}", job.failed? ? 31 : 32 ) end end - - ## - # Daemonize the worker - - def self.daemonize(*args) - if defined?(ActiveRecord) - # Sets ActiveRecord's logger to Navvy a new Logger instance - ActiveRecord::Base.logger = Logger.new(STDOUT) - end - - # If #daemonize does not receive any arguments, the options variable will - # contain an empty hash, and the ARGV of the environment will be used instead - # of the :ARGV options from Daemons#run_proc. However, if the *args param has been set - # this will be used instead of the environment's ARGV for the Daemons. - options = args.empty? ? {} : {:ARGV => args} - - # Finally, the directory store mode will be set to normal and the Daemons PID file - # will be stored inside tmp/pids of the application. - options.merge!({:dir_mode => :normal, :dir => 'tmp/pids'}) - - # Ensures that the tmp/pids folder exists so that the process id file can properly be stored - %x(mkdir -p tmp/pids) - - # Runs the Navvy Worker inside a Daemon - Daemons.run_proc('navvy', options) do - Navvy::Worker.start - end - end - end end diff --git a/navvy.gemspec b/navvy.gemspec index 18e3a68..f92f46b 100644 --- a/navvy.gemspec +++ b/navvy.gemspec @@ -1,96 +1,17 @@ -# Generated by jeweler -# DO NOT EDIT THIS FILE -# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec` -# -*- encoding: utf-8 -*- +Gem::Specification.new do |gem| + gem.name = 'navvy' + gem.version = '0.3.0' + gem.date = Date.today.to_s -Gem::Specification.new do |s| - s.name = %q{navvy} - s.version = "0.2.5" + gem.summary = "Simple background job processor inspired by delayed_job, but aiming for database agnosticism." + gem.description = "Simple background job processor inspired by delayed_job, but aiming for database agnosticism." - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Jeff Kreeftmeijer"] - s.date = %q{2010-05-29} - s.description = %q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.} - s.email = %q{jeff@kreeftmeijer.nl} - s.extra_rdoc_files = [ - "LICENSE", - "README.textile" - ] - s.files = [ - ".document", - ".gitignore", - "LICENSE", - "README.textile", - "Rakefile", - "VERSION", - "generators/navvy/navvy_generator.rb", - "generators/navvy/templates/migration.rb", - "generators/navvy/templates/script", - "lib/generators/navvy_generator.rb", - "lib/navvy.rb", - "lib/navvy/configuration.rb", - "lib/navvy/job.rb", - "lib/navvy/job/active_record.rb", - "lib/navvy/job/data_mapper.rb", - "lib/navvy/job/mongo_mapper.rb", - "lib/navvy/job/sequel.rb", - "lib/navvy/log.rb", - "lib/navvy/tasks.rb", - "lib/navvy/worker.rb", - "navvy.gemspec", - "spec/configuration_spec.rb", - "spec/job_spec.rb", - "spec/log_spec.rb", - "spec/setup/active_record.rb", - "spec/setup/data_mapper.rb", - "spec/setup/justlogging.rb", - "spec/setup/mongo_mapper.rb", - "spec/setup/rails_default_logger.rb", - "spec/setup/sequel.rb", - "spec/spec_helper.rb", - "spec/worker_spec.rb" - ] - s.homepage = %q{http://github.com/jeffkreeftmeijer/navvy} - s.rdoc_options = ["--charset=UTF-8"] - s.require_paths = ["lib"] - s.rubygems_version = %q{1.3.6} - s.summary = %q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.} - s.test_files = [ - "spec/configuration_spec.rb", - "spec/job_spec.rb", - "spec/log_spec.rb", - "spec/setup/active_record.rb", - "spec/setup/data_mapper.rb", - "spec/setup/justlogging.rb", - "spec/setup/mongo_mapper.rb", - "spec/setup/rails_default_logger.rb", - "spec/setup/sequel.rb", - "spec/spec_helper.rb", - "spec/worker_spec.rb" - ] + gem.authors = ['Jeff Kreeftmeijer'] + gem.email = 'jeff@kreeftmeijer.nl' + gem.homepage = 'http://github.com/jeffkreeftmeijer/navvy' - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 + gem.files = Dir['{generators,lib,spec}/**/*', 'README*', 'LICENSE*'] & `git ls-files -z`.split("\0") - if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q, [">= 1.2.9"]) - s.add_development_dependency(%q, [">= 0.5.2"]) - s.add_development_dependency(%q, [">= 3.8.0"]) - s.add_development_dependency(%q, [">= 1.2.5"]) - s.add_runtime_dependency(%q, [">= 1.0.10"]) - else - s.add_dependency(%q, [">= 1.2.9"]) - s.add_dependency(%q, [">= 0.5.2"]) - s.add_dependency(%q, [">= 3.8.0"]) - s.add_dependency(%q, [">= 1.2.5"]) - s.add_dependency(%q, [">= 1.0.10"]) - end - else - s.add_dependency(%q, [">= 1.2.9"]) - s.add_dependency(%q, [">= 0.5.2"]) - s.add_dependency(%q, [">= 3.8.0"]) - s.add_dependency(%q, [">= 1.2.5"]) - s.add_dependency(%q, [">= 1.0.10"]) - end + gem.add_development_dependency('rspec', [">= 1.2.9"]) + gem.add_development_dependency('yard', [">= 0.5.2"]) end diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index a7844eb..26a2969 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -5,81 +5,64 @@ Navvy.configure do |config| config.job_limit = 100 config.keep_jobs = false - config.logger = nil - config.quiet = true + config.logger = Navvy::Logger.new('/dev/null') config.sleep_time = 5 end end - + it 'should have a job limit of 100 by default' do Navvy::Job.limit.should == 100 end - + it 'should set the job limit' do Navvy.configure do |config| config.job_limit = 10 end - + Navvy::Job.limit.should == 10 end - + it 'should have keep_jobs off by default' do Navvy::Job.keep.should == false end - + it 'should set keep_jobs' do Navvy.configure do |config| config.keep_jobs = 10 end - + Navvy::Job.keep.should == 10 end - - it 'should not have a logger by default' do - Navvy::Log.logger.should == nil - end - - it 'should set the keep_jobs' do - Navvy.configure do |config| - config.logger = :rails - end - - Navvy::Log.logger.should == :rails - end - - it 'should be quiet in the specs' do - Navvy::Log.quiet.should == true - end - - it 'should turn quiet off' do + + it 'should set the logger' do Navvy.configure do |config| - config.quiet = false + config.logger = Navvy::Logger.new end - - Navvy::Log.quiet.should == false + + Navvy.logger.instance_variable_get(:@logdev).filename.should == nil end - + it 'should have a default sleep time of 5' do Navvy::Worker.sleep_time.should == 5 end - + it 'should turn quiet off' do Navvy.configure do |config| config.sleep_time = 10 end - + Navvy::Worker.sleep_time.should == 10 end - + it 'should have a default max_attempts of 25' do Navvy::Job.max_attempts.should == 25 end - + it 'should set max_attempts to 15' do Navvy.configure do |config| config.max_attempts = 15 - end - + end + Navvy::Job.max_attempts.should == 15 end -end \ No newline at end of file +end diff --git a/spec/job_spec.rb b/spec/job_spec.rb index 8b1845f..9040540 100755 --- a/spec/job_spec.rb +++ b/spec/job_spec.rb @@ -40,7 +40,7 @@ describe '.enqueue' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all end it 'should enqueue a job' do @@ -91,7 +91,7 @@ describe '.next' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.create( :object => 'Cow', :method_name => :last, @@ -122,7 +122,7 @@ it 'should find the next 10 available jobs' do jobs = Navvy::Job.next - jobs.count.should == 100 + jobs.length.should == 100 jobs.each do |job| job.should be_instance_of Navvy::Job job.method_name.to_s.should == 'speak' @@ -130,18 +130,18 @@ end it 'should find the next 2 available jobs' do - Navvy::Job.next(2).count.should == 2 + Navvy::Job.next(2).length.should == 2 end it 'should find the next 4 available jobs' do Navvy::Job.limit = 4 - Navvy::Job.next.count.should == 4 + Navvy::Job.next.length.should == 4 end end describe '.cleanup' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.create( :object => 'Cow', :method_name => :speak, @@ -186,7 +186,7 @@ describe '#run' do it 'should pass the arguments' do - delete_all_jobs + Navvy::Job.delete_all job = Navvy::Job.enqueue(Cow, :name, 'Betsy') Cow.should_receive(:name).with('Betsy') job.run @@ -194,7 +194,7 @@ describe 'when everything goes well' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.enqueue(Cow, :speak) Navvy::Job.keep = false end @@ -235,7 +235,7 @@ describe 'when a job fails' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.enqueue(Cow, :broken) end @@ -251,7 +251,7 @@ describe '#started' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.enqueue(Cow, :speak) end @@ -264,7 +264,7 @@ describe '#completed' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.enqueue(Cow, :speak) end @@ -283,7 +283,7 @@ describe '#failed' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all Navvy::Job.enqueue(Cow, :speak) end @@ -323,7 +323,7 @@ describe '#retry' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all end it 'should enqueue a child for the failed job' do @@ -388,7 +388,7 @@ describe '#times_failed' do before(:each) do - delete_all_jobs + Navvy::Job.delete_all @failed_job = Navvy::Job.create( :failed_at => Time.now ) diff --git a/spec/log_spec.rb b/spec/log_spec.rb deleted file mode 100644 index 2253c66..0000000 --- a/spec/log_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') - -class LoggerNotFound < StandardError; end - -describe Navvy::Log do - describe '.info' do - describe 'when using the rails default logger' do - before do - Navvy::Log.logger = :rails - end - - it 'should raise an error when the logger can not be found' do - lambda { Navvy::Log.info('123') }.should raise_error - end - - it 'should pass the log to Rails.logger' do - require File.expand_path(File.dirname(__FILE__) + '/setup/rails_default_logger') - Rails.logger.should_receive(:info).with('123') - Navvy::Log.info('123') - end - end - - describe 'when using justlogging' do - before do - Navvy::Log.logger = :justlogging - end - - it 'should raise an error when the logger can not be found' do - lambda { Navvy::Log.info('123') }.should raise_error - end - - it 'should pass the log to justlogging' do - require File.expand_path(File.dirname(__FILE__) + '/setup/justlogging') - Justlogging.should_receive(:log).with('123') - Navvy::Log.info('123') - end - end - - describe 'when using both the rails default logger and justlogging' do - before do - Navvy::Log.logger = [:rails, :justlogging] - end - - it 'should pass the log to justlogging' do - Rails.logger.should_receive(:info).with('123') - Justlogging.should_receive(:log).with('123') - Navvy::Log.info('123') - end - end - - describe 'when not using any logger' do - before do - Navvy::Log.logger = nil - end - - it 'should not log' do - Rails.logger.should_not_receive(:info) - Justlogging.should_not_receive(:log) - Navvy::Log.info('123') - end - end - end -end diff --git a/spec/logger_spec.rb b/spec/logger_spec.rb new file mode 100644 index 0000000..3f03d71 --- /dev/null +++ b/spec/logger_spec.rb @@ -0,0 +1,23 @@ +require File.expand_path(File.dirname(__FILE__) + '/spec_helper') + +describe Navvy::Logger do + describe '#colorized_info' do + describe 'when logging to STDOUT' do + it 'should use the provided colors' do + logger = Navvy::Logger.new + logger.should_not_receive(:info).with('colors!') + logger.should_receive(:info).with("\e[32mcolors!\e[0m") + logger.colorized_info 'colors!', 32 + end + end + + describe 'when logging to a file' do + it 'should not use the provided colors' do + logger = Navvy::Logger.new('/dev/null') + logger.should_receive(:info).with('colors!') + logger.should_not_receive(:info).with("\e[32mcolors!\e[0m") + logger.colorized_info 'colors!', 32 + end + end + end +end diff --git a/spec/setup/active_record.rb b/spec/setup/active_record.rb index c267181..514d042 100644 --- a/spec/setup/active_record.rb +++ b/spec/setup/active_record.rb @@ -1,5 +1,4 @@ require File.expand_path(File.dirname(__FILE__) + '/../../lib/navvy/job/active_record') -require 'rubygems' ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => '/tmp/navvy_test.sqlite') diff --git a/spec/setup/justlogging.rb b/spec/setup/justlogging.rb deleted file mode 100644 index c191e9e..0000000 --- a/spec/setup/justlogging.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Justlogging - def self.log(text);end -end diff --git a/spec/setup/mongoid.rb b/spec/setup/mongoid.rb new file mode 100644 index 0000000..598e735 --- /dev/null +++ b/spec/setup/mongoid.rb @@ -0,0 +1,9 @@ +require 'mongoid' + +Mongoid.configure do |config| + name = "navvy_test" + config.allow_dynamic_fields = false + config.master = Mongo::Connection.new.db(name) +end + +require File.expand_path(File.dirname(__FILE__) + '/../../lib/navvy/job/mongoid') diff --git a/spec/setup/rails_default_logger.rb b/spec/setup/rails_default_logger.rb deleted file mode 100644 index 268bba9..0000000 --- a/spec/setup/rails_default_logger.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Rails - def self.logger - Logger - end - - class Logger - def self.info(text);end - end -end diff --git a/spec/setup/sequel.rb b/spec/setup/sequel.rb index cf63d5b..9b034af 100644 --- a/spec/setup/sequel.rb +++ b/spec/setup/sequel.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'sequel' Sequel.sqlite('/tmp/navvy_test.sqlite') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6709ebb..40a25d8 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,16 +7,6 @@ Spec::Runner.configure do |config| end -def delete_all_jobs - if defined? Navvy::Job.delete_all - Navvy::Job.delete_all - elsif defined? Navvy::Job.all.destroy - Navvy::Job.all.destroy - else - Navvy::Job.delete - end -end - def job_count if defined? Navvy::Job.count Navvy::Job.count @@ -50,7 +40,3 @@ def self.broken end end end - -Navvy.configure do |config| - config.quiet = true -end