├── .bundle └── config ├── .gitignore ├── .travis.yml ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── Rakefile ├── lib ├── resque-meta.rb └── resque │ └── plugins │ ├── meta.rb │ └── meta │ ├── metadata.rb │ └── version.rb ├── resque-meta.gemspec └── test ├── meta_test.rb ├── redis-test.conf └── test_helper.rb /.bundle/config: -------------------------------------------------------------------------------- 1 | --- 2 | BUNDLE_DISABLE_SHARED_GEMS: "1" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dump.rdb 2 | doc/* 3 | pkg/* 4 | *.gem 5 | .bundle 6 | Gemfile.lock 7 | /tags 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.8.7 3 | - 1.9.3 4 | - 2.0.0 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in resque-meta.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ## 2.0.1 (2013-11-25) 2 | 3 | * Include Resque::Helpers for [breaking change in resque 1.25][resque125] - [jsanders][jsanders] [Pull Request][pull13], [mcfiredrill][mcfiredrill] [Pull Request][pull12] 4 | 5 | ## 2.0.0 (2012-12-04) 6 | 7 | * Use redis setex to expire metadata from Pascal Brogle - [broglep-koubachi][broglep-koubachi] [Pull Request][pull9] 8 | * setex require redis 2+, hence the major version bump 9 | 10 | ## 1.0.3 (2011-02-10) 11 | 12 | * Document and test Metadata#save from Kurt Werle - [kwerle][kwerle] [Pull Request][pull3] 13 | * Metadata#seconds_enqueued and #seconds_processing are more precise from [Steve Howell][showell] 14 | 15 | ## 1.0.2 (2010-11-03) 16 | 17 | * Use a more random default meta_id with SHA1 from Cory Forsyth - [bantic][bantic] [Pull Request][pull2] 18 | 19 | ## 1.0.1 (2010-09-10) 20 | 21 | * Add lib/resque-meta.rb for convenient requiring 22 | * Doc fixes from Jeffrey Chupp - [semanticart][semanticart] [Pull Request][pull1] 23 | * Depend more strictly on resque (>= 1.8, < 2.0) 24 | 25 | ## 1.0.0 (2010-06-04) 26 | 27 | * Initial release 28 | 29 | [bantic]: https://github.com/bantic 30 | [showell]: http://librelist.com/browser//resque/2010/12/8/recording-time-in-queue-and-time-to-process/#1de6433232ac1264286feeed1f8f219e 31 | [semanticart]: https://github.com/semanticart 32 | [kwerle]: https://github.com/kwerle 33 | [broglep-koubachi]: https://github.com/broglep-koubachi 34 | [pull1]: https://github.com/lmarlow/resque-meta/pull/1 35 | [pull2]: https://github.com/lmarlow/resque-meta/pull/2 36 | [pull3]: https://github.com/lmarlow/resque-meta/pull/3 37 | [pull9]: https://github.com/lmarlow/resque-meta/pull/9 38 | [resque125]: https://github.com/resque/resque/issues/1150 39 | [jsanders]: https://github.com/jsanders 40 | [mcfiredrill]: https://github.com/mcfiredrill 41 | [pull12]: https://github.com/lmarlow/resque-meta/pull/12 42 | [pull13]: https://github.com/lmarlow/resque-meta/pull/13 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Lee Marlow 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | Software), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Resque Meta 2 | =========== 3 | 4 | [![Build Status](https://secure.travis-ci.org/lmarlow/resque-meta.png)](http://travis-ci.org/lmarlow/resque-meta) 5 | 6 | A [Resque][rq] plugin. Requires Resque 1.8 and Redis 2+. 7 | 8 | If you want to be able to add metadata for a job 9 | to track anything you want, extend it with this module. 10 | 11 | For example: 12 | 13 | require 'resque-meta' 14 | 15 | class MyJob 16 | extend Resque::Plugins::Meta 17 | 18 | def self.perform(meta_id, *args) 19 | heavy_lifting 20 | end 21 | end 22 | 23 | meta0 = MyJob.enqueue('stuff') 24 | meta0.enqueued_at # => 'Wed May 19 13:42:41 -0600 2010' 25 | meta0.meta_id # => '03c9e1a045ad012dd20500264a19273c' 26 | meta0['foo'] = 'bar' # => 'bar' 27 | meta0.save 28 | 29 | # later 30 | meta1 = MyJob.get_meta('03c9e1a045ad012dd20500264a19273c') 31 | meta1.job_class # => MyJob 32 | meta1.enqueued_at # => 'Wed May 19 13:42:41 -0600 2010' 33 | meta1['foo'] # => 'bar' 34 | 35 | [rq]: http://github.com/resque/resque 36 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rake/testtask' 5 | Rake::TestTask.new do |t| 6 | t.libs << 'lib' 7 | t.pattern = 'test/**/*_test.rb' 8 | t.verbose = false 9 | end 10 | 11 | task :default => :test 12 | -------------------------------------------------------------------------------- /lib/resque-meta.rb: -------------------------------------------------------------------------------- 1 | require 'resque/plugins/meta' 2 | -------------------------------------------------------------------------------- /lib/resque/plugins/meta.rb: -------------------------------------------------------------------------------- 1 | require 'digest/sha1' 2 | require 'resque' 3 | require 'resque/plugins/meta/version' 4 | require 'resque/plugins/meta/metadata' 5 | 6 | module Resque 7 | module Plugins 8 | # If you want to be able to add metadata for a job 9 | # to track anything you want, extend it with this module. 10 | # 11 | # For example: 12 | # 13 | # require 'resque-meta' 14 | # 15 | # class MyJob 16 | # extend Resque::Plugins::Meta 17 | # 18 | # def self.perform(meta_id, *args) 19 | # heavy_lifting 20 | # end 21 | # end 22 | # 23 | # meta0 = MyJob.enqueue('stuff') 24 | # meta0.enqueued_at # => 'Wed May 19 13:42:41 -0600 2010' 25 | # meta0.meta_id # => '03c9e1a045ad012dd20500264a19273c' 26 | # meta0['foo'] = 'bar' # => 'bar' 27 | # meta0.save 28 | # 29 | # # later 30 | # meta1 = MyJob.get_meta('03c9e1a045ad012dd20500264a19273c') 31 | # meta1.job_class # => MyJob 32 | # meta1.enqueued_at # => 'Wed May 19 13:42:41 -0600 2010' 33 | # meta1['foo'] # => 'bar' 34 | module Meta 35 | 36 | # Override in your job to control the metadata id. It is 37 | # passed the same arguments as `perform`, that is, your job's 38 | # payload. 39 | def meta_id(*args) 40 | Digest::SHA1.hexdigest([ Time.now.to_f, rand, self, args ].join) 41 | end 42 | 43 | # Override in your job to control the how many seconds a job's 44 | # metadata will live after it finishes. Defaults to 24 hours. 45 | # Return nil or 0 to set them to never expire. 46 | def expire_meta_in 47 | 24 * 60 * 60 48 | end 49 | 50 | # Override in your job to control how many seconds a job's 51 | # metadata will live after it is enqueued and *before* it finishes. 52 | # This includes the condition 53 | # where the job and metadata are never finished because of a 54 | # shutdown or server crash. Defaults to 0 (i.e. 55 | # forever). Return nil or 0 to set them to never expire. 56 | # Use caution: this value should be longer than your jobs take to run! 57 | def before_finish_expire_in 58 | 0 59 | end 60 | 61 | # Enqueues a job in Resque and return the association metadata. 62 | # The meta_id in the returned object can be used to fetch the 63 | # metadata again in the future. 64 | def enqueue(*args) 65 | meta = Metadata.new({'meta_id' => meta_id(args), 'job_class' => self.to_s}) 66 | meta.save 67 | Resque.enqueue(self, meta.meta_id, *args) 68 | meta 69 | end 70 | 71 | def store_meta(meta) 72 | key = "meta:#{meta.meta_id}" 73 | json = Resque.encode(meta.data) 74 | if meta.expire_at > 0 75 | Resque.redis.setex(key, meta.expire_at - Time.now.to_i, json) 76 | else 77 | Resque.redis.set(key, json) 78 | end 79 | meta 80 | end 81 | 82 | # Retrieve the metadata for a given job. If you call this 83 | # from a class that extends Meta, then the metadata will 84 | # only be returned if the metadata for that id is for the 85 | # same class. Explicitly, calling Meta.get_meta(some_id) 86 | # will return the metadata for a job of any type. 87 | def get_meta(meta_id) 88 | key = "meta:#{meta_id}" 89 | if json = Resque.redis.get(key) 90 | data = Resque.decode(json) 91 | if self == Meta || self.to_s == data['job_class'] 92 | Metadata.new(data) 93 | end 94 | end 95 | end 96 | module_function :get_meta 97 | public :get_meta 98 | 99 | def before_perform_meta(meta_id, *args) 100 | if meta = get_meta(meta_id) 101 | meta.start! 102 | end 103 | end 104 | 105 | def after_perform_meta(meta_id, *args) 106 | if meta = get_meta(meta_id) 107 | meta.finish! 108 | end 109 | end 110 | 111 | def on_failure_meta(e, meta_id, *args) 112 | if meta = get_meta(meta_id) 113 | meta.fail! 114 | end 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /lib/resque/plugins/meta/metadata.rb: -------------------------------------------------------------------------------- 1 | require 'time' 2 | 3 | module Resque 4 | module Plugins 5 | module Meta 6 | class Metadata 7 | include Resque::Helpers 8 | attr_reader :job_class, :meta_id, :data, :enqueued_at, :expire_in, :before_finish_expire_in 9 | 10 | def initialize(data_hash) 11 | data_hash['enqueued_at'] ||= to_time_format_str(Time.now) 12 | @data = data_hash 13 | @meta_id = data_hash['meta_id'].dup 14 | @enqueued_at = from_time_format_str('enqueued_at') 15 | @job_class = data_hash['job_class'] 16 | if @job_class.is_a?(String) 17 | @job_class = constantize(data_hash['job_class']) 18 | else 19 | data_hash['job_class'] = @job_class.to_s 20 | end 21 | @expire_in = @job_class.expire_meta_in || 0 22 | @before_finish_expire_in = @job_class.before_finish_expire_in || 0 23 | end 24 | 25 | # Reload the metadata from the store 26 | def reload! 27 | if new_meta = job_class.get_meta(meta_id) 28 | @data = new_meta.data 29 | end 30 | self 31 | end 32 | 33 | # Save the metadata 34 | def save 35 | job_class.store_meta(self) 36 | self 37 | end 38 | 39 | def [](key) 40 | data[key] 41 | end 42 | 43 | def []=(key, val) 44 | data[key.to_s] = val 45 | end 46 | 47 | def start! 48 | @started_at = Time.now 49 | self['started_at'] = to_time_format_str(@started_at) 50 | save 51 | end 52 | 53 | def started_at 54 | @started_at ||= from_time_format_str('started_at') 55 | end 56 | 57 | def finish! 58 | data['succeeded'] = true unless data.has_key?('succeeded') 59 | @finished_at = Time.now 60 | self['finished_at'] = to_time_format_str(@finished_at) 61 | save 62 | end 63 | 64 | def finished_at 65 | @finished_at ||= from_time_format_str('finished_at') 66 | end 67 | 68 | def expire_at 69 | # expiry after finished 70 | if finished? && expire_in > 0 71 | finished_at.to_i + expire_in 72 | # expiry after enqueued 73 | elsif before_finish_expire_in > 0 74 | enqueued_at.to_i + before_finish_expire_in 75 | # default ttl is forever 76 | else 77 | 0 78 | end 79 | end 80 | 81 | def enqueued? 82 | !started? 83 | end 84 | 85 | def working? 86 | started? && !finished? 87 | end 88 | 89 | def started? 90 | started_at ? true :false 91 | end 92 | 93 | def finished? 94 | finished_at ? true : false 95 | end 96 | 97 | def fail! 98 | self['succeeded'] = false 99 | finish! 100 | end 101 | 102 | def succeeded? 103 | finished? ? self['succeeded'] : nil 104 | end 105 | 106 | def failed? 107 | finished? ? !self['succeeded'] : nil 108 | end 109 | 110 | def seconds_enqueued 111 | (started_at || Time.now).to_f - enqueued_at.to_f 112 | end 113 | 114 | def seconds_processing 115 | if started? 116 | (finished_at || Time.now).to_f - started_at.to_f 117 | else 118 | 0 119 | end 120 | end 121 | 122 | protected 123 | 124 | def from_time_format_str(key) 125 | (t = self[key]) && Time.parse(t) 126 | end 127 | 128 | def to_time_format_str(time) 129 | time.utc.iso8601(6) 130 | end 131 | end 132 | end 133 | end 134 | end 135 | -------------------------------------------------------------------------------- /lib/resque/plugins/meta/version.rb: -------------------------------------------------------------------------------- 1 | module Resque 2 | module Plugins 3 | module Meta 4 | Version = '2.0.1' 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /resque-meta.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/resque/plugins/meta/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.name = "resque-meta" 5 | s.version = Resque::Plugins::Meta::Version 6 | s.date = Time.now.strftime('%Y-%m-%d') 7 | s.summary = "A Resque plugin for storing job metadata." 8 | s.homepage = "http://github.com/lmarlow/resque-meta" 9 | s.email = "lee.marlow@gmail.com" 10 | s.authors = [ "Lee Marlow" ] 11 | s.has_rdoc = false 12 | 13 | s.files = %w( README.md Rakefile LICENSE ) 14 | s.files += Dir.glob("lib/**/*") 15 | s.files += Dir.glob("test/**/*") 16 | 17 | s.description = < 'Wed May 19 13:42:41 -0600 2010' 35 | meta0.meta_id # => '03c9e1a045ad012dd20500264a19273c' 36 | meta0['foo'] = 'bar' # => 'bar' 37 | meta0.save 38 | 39 | # later 40 | meta1 = MyJob.get_meta('03c9e1a045ad012dd20500264a19273c') 41 | meta1.job_class # => MyJob 42 | meta1.enqueued_at # => 'Wed May 19 13:42:41 -0600 2010' 43 | meta1['foo'] # => 'bar' 44 | desc 45 | 46 | if s.respond_to? :specification_version then 47 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION 48 | s.specification_version = 3 49 | 50 | s.add_runtime_dependency('resque', ["~> 1.8"]) 51 | s.add_development_dependency('rake', ["~> 0.9.2"]) 52 | s.add_development_dependency('json') 53 | else 54 | s.add_dependency('resque', ["~> 1.8"]) 55 | s.add_dependency('rake', ["~> 0.9.2"]) 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/meta_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/test_helper' 2 | require 'resque-meta' 3 | 4 | class MetaJob 5 | extend Resque::Plugins::Meta 6 | @queue = :test 7 | 8 | def self.expire_meta_in 9 | 1 10 | end 11 | 12 | def self.perform(meta_id, key, val) 13 | meta = get_meta(meta_id) 14 | meta[key] = val 15 | meta.save 16 | end 17 | end 18 | 19 | class AnotherJob 20 | extend Resque::Plugins::Meta 21 | @queue = :test 22 | 23 | def self.perform(meta_id) 24 | end 25 | end 26 | 27 | class SlowJob 28 | extend Resque::Plugins::Meta 29 | @queue = :test 30 | 31 | def self.expire_meta_in 32 | 1 33 | end 34 | 35 | def self.perform(meta_id, key, val) 36 | meta = get_meta(meta_id) 37 | meta[key] = val 38 | meta.save 39 | sleep 1 40 | end 41 | end 42 | 43 | class FailingJob 44 | extend Resque::Plugins::Meta 45 | @queue = :test 46 | 47 | def self.perform(*args) 48 | raise 'boom' 49 | end 50 | end 51 | 52 | class TransientJob 53 | extend Resque::Plugins::Meta 54 | @queue = :test 55 | 56 | def self.perform(meta_id) 57 | end 58 | 59 | def self.before_finish_expire_in 60 | 1 61 | end 62 | end 63 | 64 | class MetaTest < Test::Unit::TestCase 65 | def setup 66 | Resque.redis.flushall 67 | end 68 | 69 | def test_meta_version 70 | assert_equal '2.0.1', Resque::Plugins::Meta::Version 71 | end 72 | 73 | def test_lint 74 | assert_nothing_raised do 75 | Resque::Plugin.lint(Resque::Plugins::Meta) 76 | end 77 | end 78 | 79 | def test_resque_version 80 | major, minor, patch = Resque::Version.split('.') 81 | assert_equal 1, major.to_i 82 | assert minor.to_i >= 8 83 | end 84 | 85 | def test_enqueued_metadata 86 | now = Time.now 87 | meta = MetaJob.enqueue('foo', 'bar') 88 | assert_not_nil meta 89 | assert_not_nil meta.meta_id 90 | assert meta.enqueued_at.to_f > now.to_f, "#{meta.enqueued_at} should be after #{now}" 91 | assert meta.seconds_enqueued > 0.0, "seconds_enqueued should be greater than zero" 92 | assert meta.enqueued? 93 | assert !meta.started? 94 | assert_equal 0, meta.seconds_processing 95 | assert !meta.finished? 96 | assert_nil meta['foo'] 97 | assert_equal Resque::Plugins::Meta::Metadata, meta.class 98 | assert_equal MetaJob, meta.job_class 99 | end 100 | 101 | def test_processed_job 102 | meta = MetaJob.enqueue('foo', 'bar') 103 | assert_nil meta['foo'] 104 | worker = Resque::Worker.new(:test) 105 | worker.work(0) 106 | 107 | meta = MetaJob.get_meta(meta.meta_id) 108 | assert_equal MetaJob, meta.job_class 109 | assert meta.started? 110 | assert meta.finished?, 'Job should be finished' 111 | assert meta.succeeded?, 'Job should have succeeded' 112 | assert !meta.enqueued? 113 | assert meta.seconds_enqueued > 0.0, "seconds_enqueued should be greater than zero" 114 | assert meta.seconds_processing > 0.0, "seconds_processing should be greater than zero" 115 | assert_equal 'bar', meta['foo'], "'foo' not found in #{meta.inspect}" 116 | end 117 | 118 | def test_wrong_id_for_class 119 | meta = MetaJob.enqueue('foo', 'bar') 120 | 121 | assert_nil AnotherJob.get_meta(meta.meta_id) 122 | assert_not_nil Resque::Plugins::Meta.get_meta(meta.meta_id) 123 | end 124 | 125 | def test_expired_metadata 126 | meta = MetaJob.enqueue('foo', 'bar') 127 | worker = Resque::Worker.new(:test) 128 | worker.work(0) 129 | 130 | sleep 2 131 | meta = MetaJob.get_meta(meta.meta_id) 132 | assert_nil meta 133 | end 134 | 135 | def test_expired_metadata_before_finished 136 | meta = TransientJob.enqueue() 137 | worker = Resque::Worker.new(:test) 138 | assert meta = TransientJob.get_meta(meta.meta_id) 139 | 140 | sleep 2 141 | meta = TransientJob.get_meta(meta.meta_id) 142 | assert_equal nil, meta 143 | end 144 | 145 | def test_slow_job 146 | meta = SlowJob.enqueue('foo', 'bar') 147 | worker = Resque::Worker.new(:test) 148 | thread = Thread.new { worker.work(0) } 149 | 150 | sleep 0.1 151 | meta = SlowJob.get_meta(meta.meta_id) 152 | assert !meta.enqueued? 153 | assert meta.started? 154 | assert meta.working? 155 | assert !meta.finished? 156 | 157 | thread.join # job should be done 158 | meta.reload! 159 | assert !meta.enqueued? 160 | assert meta.started? 161 | assert !meta.working? 162 | assert meta.finished? 163 | assert meta.succeeded? 164 | assert !meta.failed? 165 | 166 | sleep 2 167 | assert_nil Resque::Plugins::Meta.get_meta(meta.meta_id) 168 | end 169 | 170 | def test_failing_job 171 | meta = FailingJob.enqueue() 172 | assert_nil meta.failed? 173 | worker = Resque::Worker.new(:test) 174 | worker.work(0) 175 | 176 | meta.reload! 177 | assert meta.finished? 178 | assert meta.failed? 179 | assert !meta.succeeded? 180 | end 181 | 182 | def test_saving_additional_metadata 183 | meta = MetaJob.enqueue('stuff') 184 | meta['foo'] = 'bar' 185 | meta.save 186 | 187 | # later 188 | meta = MetaJob.get_meta(meta.meta_id) 189 | assert_equal 'bar', meta['foo'] 190 | end 191 | end 192 | -------------------------------------------------------------------------------- /test/redis-test.conf: -------------------------------------------------------------------------------- 1 | # Redis configuration file example 2 | 3 | # By default Redis does not run as a daemon. Use 'yes' if you need it. 4 | # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. 5 | daemonize yes 6 | 7 | # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default. 8 | # You can specify a custom pid file location here. 9 | pidfile ./test/redis-test.pid 10 | 11 | # Accept connections on the specified port, default is 6379 12 | port 9736 13 | 14 | # If you want you can bind a single interface, if the bind option is not 15 | # specified all the interfaces will listen for connections. 16 | # 17 | # bind 127.0.0.1 18 | 19 | # Close the connection after a client is idle for N seconds (0 to disable) 20 | timeout 300 21 | 22 | # Save the DB on disk: 23 | # 24 | # save 25 | # 26 | # Will save the DB if both the given number of seconds and the given 27 | # number of write operations against the DB occurred. 28 | # 29 | # In the example below the behaviour will be to save: 30 | # after 900 sec (15 min) if at least 1 key changed 31 | # after 300 sec (5 min) if at least 10 keys changed 32 | # after 60 sec if at least 10000 keys changed 33 | save 900 1 34 | save 300 10 35 | save 60 10000 36 | 37 | # The filename where to dump the DB 38 | dbfilename dump.rdb 39 | 40 | # For default save/load DB in/from the working directory 41 | # Note that you must specify a directory not a file name. 42 | dir ./test/ 43 | 44 | # Set server verbosity to 'debug' 45 | # it can be one of: 46 | # debug (a lot of information, useful for development/testing) 47 | # notice (moderately verbose, what you want in production probably) 48 | # warning (only very important / critical messages are logged) 49 | loglevel debug 50 | 51 | # Specify the log file name. Also 'stdout' can be used to force 52 | # the demon to log on the standard output. Note that if you use standard 53 | # output for logging but daemonize, logs will be sent to /dev/null 54 | logfile stdout 55 | 56 | # Set the number of databases. The default database is DB 0, you can select 57 | # a different one on a per-connection basis using SELECT where 58 | # dbid is a number between 0 and 'databases'-1 59 | databases 16 60 | 61 | ################################# REPLICATION ################################# 62 | 63 | # Master-Slave replication. Use slaveof to make a Redis instance a copy of 64 | # another Redis server. Note that the configuration is local to the slave 65 | # so for example it is possible to configure the slave to save the DB with a 66 | # different interval, or to listen to another port, and so on. 67 | 68 | # slaveof 69 | 70 | ################################## SECURITY ################################### 71 | 72 | # Require clients to issue AUTH before processing any other 73 | # commands. This might be useful in environments in which you do not trust 74 | # others with access to the host running redis-server. 75 | # 76 | # This should stay commented out for backward compatibility and because most 77 | # people do not need auth (e.g. they run their own servers). 78 | 79 | # requirepass foobared 80 | 81 | ################################### LIMITS #################################### 82 | 83 | # Set the max number of connected clients at the same time. By default there 84 | # is no limit, and it's up to the number of file descriptors the Redis process 85 | # is able to open. The special value '0' means no limts. 86 | # Once the limit is reached Redis will close all the new connections sending 87 | # an error 'max number of clients reached'. 88 | 89 | # maxclients 128 90 | 91 | # Don't use more memory than the specified amount of bytes. 92 | # When the memory limit is reached Redis will try to remove keys with an 93 | # EXPIRE set. It will try to start freeing keys that are going to expire 94 | # in little time and preserve keys with a longer time to live. 95 | # Redis will also try to remove objects from free lists if possible. 96 | # 97 | # If all this fails, Redis will start to reply with errors to commands 98 | # that will use more memory, like SET, LPUSH, and so on, and will continue 99 | # to reply to most read-only commands like GET. 100 | # 101 | # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a 102 | # 'state' server or cache, not as a real DB. When Redis is used as a real 103 | # database the memory usage will grow over the weeks, it will be obvious if 104 | # it is going to use too much memory in the long run, and you'll have the time 105 | # to upgrade. With maxmemory after the limit is reached you'll start to get 106 | # errors for write operations, and this may even lead to DB inconsistency. 107 | 108 | # maxmemory 109 | 110 | ############################### ADVANCED CONFIG ############################### 111 | 112 | # Use object sharing. Can save a lot of memory if you have many common 113 | # string in your dataset, but performs lookups against the shared objects 114 | # pool so it uses more CPU and can be a bit slower. Usually it's a good 115 | # idea. 116 | # 117 | # When object sharing is enabled (shareobjects yes) you can use 118 | # shareobjectspoolsize to control the size of the pool used in order to try 119 | # object sharing. A bigger pool size will lead to better sharing capabilities. 120 | # In general you want this value to be at least the double of the number of 121 | # very common strings you have in your dataset. 122 | # 123 | # WARNING: object sharing is experimental, don't enable this feature 124 | # in production before of Redis 1.0-stable. Still please try this feature in 125 | # your development environment so that we can test it better. 126 | # shareobjects no 127 | # shareobjectspoolsize 1024 128 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | dir = File.dirname(File.expand_path(__FILE__)) 2 | $LOAD_PATH.unshift dir + '/../lib' 3 | require 'test/unit' 4 | require 'rubygems' 5 | require 'resque' 6 | 7 | # 8 | # make sure we can run redis 9 | # 10 | 11 | if !system("which redis-server") || !system("which redis-cli") 12 | puts '', "** missing redis-server and/or redis-cli" 13 | puts "** try running `sudo rake install`" 14 | abort '' 15 | end 16 | 17 | 18 | # 19 | # start our own redis when the tests start, 20 | # kill it when they end 21 | # 22 | 23 | at_exit do 24 | next if $! 25 | 26 | exit_code = Test::Unit::AutoRunner.run 27 | 28 | puts "Killing test redis server at localhost:9736..." 29 | `redis-cli -p 9736 shutdown` 30 | `rm -f #{dir}/dump.rdb` 31 | exit exit_code 32 | end 33 | 34 | puts "Starting redis for testing at localhost:9736..." 35 | `redis-server #{dir}/redis-test.conf` 36 | Resque.redis = 'localhost:9736' 37 | --------------------------------------------------------------------------------