resque-unique_by_arity 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6f9ce19b6bc1fb732d1e65041619ab23e3ec260e
4
+ data.tar.gz: 8378dafafc81c1fbc4f8cb8accc4ae21b9833604
5
+ SHA512:
6
+ metadata.gz: 354198da378d793f142af7ce1d4938af08544f8208cff62bca8af90460005a773f5205b212afdb7454aac20ebedf840588005ea3679f1ba8ebed05dc106de2b3
7
+ data.tar.gz: b61e3cb714f9b19d8a52d8bd3285d0d47de32439858cf44e256758ef633378a2dfb06d153fe9b21469da0858a07b389f8d49501dcb9aa2fbd36e576442b56e97
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.0.0
5
+ before_install: gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in resque-unique_by_arity.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # Resque::UniqueByArity
2
+
3
+ Usage:
4
+
5
+ ```ruby
6
+ class MyJob
7
+ include UniqueByArity::Cop.new(
8
+ arity_for_uniqueness: 1,
9
+ unique_at_runtime: true,
10
+ unique_in_queue: true
11
+ )
12
+ end
13
+ ```
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'resque-unique_by_arity'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install resque-unique_by_arity
30
+
31
+ ## Usage
32
+
33
+ ```ruby
34
+ class MyJob
35
+ include UniqueByArity::Cop.new(
36
+ arity_for_uniqueness: 1,
37
+ unique_at_runtime: true,
38
+ unique_in_queue: true
39
+ )
40
+ end
41
+ ```
42
+
43
+ ## Development
44
+
45
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
48
+
49
+ ## Contributing
50
+
51
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pboling/resque-unique_by_arity.
52
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "resque/unique_by_arity"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,77 @@
1
+ require "resque-lonely_job"
2
+ require "resque_solo"
3
+
4
+ require "resque/unique_by_arity/version"
5
+ require "resque/unique_by_arity/configuration"
6
+ require "resque/unique_by_arity/cop"
7
+ require "resque/unique_by_arity/cop_modulizer"
8
+
9
+ # Usage:
10
+ #
11
+ # class MyJob
12
+ # include UniqueByArity::Cop.new(
13
+ # arity_for_uniqueness: 1,
14
+ # unique_at_runtime: true,
15
+ # unique_in_queue: true
16
+ # )
17
+ # end
18
+ #
19
+ module Resque
20
+ module UniqueByArity
21
+ def unique_log(message, config_proxy = nil)
22
+ config_proxy ||= self
23
+ config_proxy.unique_logger.send(config_proxy.unique_log_level, message) if config_proxy.unique_logger
24
+ end
25
+
26
+ # There are times when the class will need access to the configuration object,
27
+ # such as to override it per instance method
28
+ def uniq_config
29
+ @uniqueness_configuration
30
+ end
31
+
32
+ # For per-class config with a block
33
+ def uniqueness_configure
34
+ @uniqueness_configuration ||= Configuration.new
35
+ yield(@uniqueness_configuration)
36
+ end
37
+
38
+ #### CONFIG ####
39
+ class << self
40
+ attr_accessor :uniqueness_configuration
41
+ end
42
+ def uniqueness_config_reset(config = Configuration.new)
43
+ @uniqueness_configuration = config
44
+ end
45
+ def uniqueness_log_level
46
+ @uniqueness_configuration.log_level
47
+ end
48
+ def uniqueness_log_level=(log_level)
49
+ @uniqueness_configuration.log_level = log_level
50
+ end
51
+ def uniqueness_arity_for_uniqueness
52
+ @uniqueness_configuration.arity_for_uniqueness
53
+ end
54
+ def uniqueness_arity_for_uniqueness=(arity_for_uniqueness)
55
+ @uniqueness_configuration.arity_for_uniqueness = arity_for_uniqueness
56
+ end
57
+ def uniqueness_lock_after_execution_period
58
+ @uniqueness_configuration.lock_after_execution_period
59
+ end
60
+ def uniqueness_lock_after_execution_period=(lock_after_execution_period)
61
+ @uniqueness_configuration.lock_after_execution_period = lock_after_execution_period
62
+ end
63
+ def uniqueness_unique_at_runtime
64
+ @uniqueness_configuration.unique_at_runtime
65
+ end
66
+ def uniqueness_unique_at_runtime=(unique_at_runtime)
67
+ @uniqueness_configuration.unique_at_runtime = unique_at_runtime
68
+ end
69
+ def uniqueness_unique_in_queue
70
+ @uniqueness_configuration.unique_in_queue
71
+ end
72
+ def uniqueness_unique_in_queue=(unique_in_queue)
73
+ @uniqueness_configuration.unique_in_queue = unique_in_queue
74
+ end
75
+ self.uniqueness_configuration = Configuration.new # setup defaults
76
+ end
77
+ end
@@ -0,0 +1,37 @@
1
+ require 'logger'
2
+ module Resque
3
+ module UniqueByArity
4
+ class Configuration
5
+ attr_accessor :logger
6
+ attr_accessor :log_level
7
+ attr_accessor :arity_for_uniqueness
8
+ attr_accessor :lock_after_execution_period
9
+ attr_accessor :unique_at_runtime
10
+ attr_accessor :unique_in_queue
11
+ alias :debug_logger :logger
12
+ alias :debug_log_level :log_level
13
+ alias :debug_arity_for_uniqueness :arity_for_uniqueness
14
+ alias :debug_lock_after_execution_period :lock_after_execution_period
15
+ alias :debug_unique_at_runtime :unique_at_runtime
16
+ alias :debug_unique_in_queue :unique_in_queue
17
+ def initialize(**options)
18
+ @logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
19
+ @log_level = options.key?(:log_level) ? options[:log_level] : :debug
20
+ @arity_for_uniqueness = options.key?(:arity_for_uniqueness) ? options[:arity_for_uniqueness] : 1
21
+ @lock_after_execution_period = options.key?(:lock_after_execution_period) ? options[:lock_after_execution_period] : nil
22
+ @unique_at_runtime = options.key?(:unique_at_runtime) ? options[:unique_at_runtime] : false
23
+ @unique_in_queue = options.key?(:unique_in_queue) ? options[:unique_in_queue] : false
24
+ end
25
+ def to_hash
26
+ {
27
+ logger: logger,
28
+ log_level: log_level,
29
+ arity_for_uniqueness: arity_for_uniqueness,
30
+ lock_after_execution_period: lock_after_execution_period,
31
+ unique_at_runtime: unique_at_runtime,
32
+ unique_in_queue: unique_in_queue
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module Resque
2
+ module UniqueByArity
3
+ class Cop < Module
4
+ def initialize(**config)
5
+ @configuration = Resque::UniqueByArity::Configuration.new(**config)
6
+ end
7
+ def included(base)
8
+ return unless @configuration
9
+ base.send(:extend, Resque::UniqueByArity)
10
+ base.uniqueness_config_reset(@configuration.dup)
11
+
12
+ # gem is resque_solo, which is a rewrite of resque-loner
13
+ # see: https://github.com/neighborland/resque_solo
14
+ # defines a redis_key method, which if we are not careful, conflicts with a custom redis_key we set here
15
+ base.send(:include, Resque::Plugins::UniqueJob) if @configuration.unique_in_queue
16
+
17
+ # gem is resque-lonely_job
18
+ # see: https://github.com/wallace/resque-lonely_job
19
+ base.send(:extend, Resque::Plugins::LonelyJob) if @configuration.unique_at_runtime
20
+
21
+ uniqueness_cop_module = Resque::UniqueByArity::CopModulizer.to_mod(@configuration)
22
+ # This will override methods from both plugins above, if configured for both
23
+ base.send(:extend, uniqueness_cop_module)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,52 @@
1
+ module Resque
2
+ module UniqueByArity
3
+ module CopModulizer
4
+ def self.to_mod(configuration)
5
+ Module.new do
6
+ if configuration.unique_in_queue
7
+ # Returns a string, used by LonelyJob, that will be used as the redis key
8
+ # The example in the readme is bad. The args passed to this method are like:
9
+ # [{:class=>"MakeCompanyReport", :args=>[1]}]
10
+ # This is identical to the version from Resque::Plugins::UniqueJob
11
+ # and we do not want the version from Resque::Plugins::LonelyJob to be used.
12
+ # Payload is what Resque stored for this job along with the job's class name:
13
+ # a hash containing :class and :args
14
+ define_method(:redis_key) do |payload|
15
+ puts "overriding redis_key in #{self}"
16
+ begin
17
+ payload = Resque.decode(Resque.encode(payload))
18
+ job = payload["class"]
19
+ args = payload["args"]
20
+ args.map! do |arg|
21
+ arg.is_a?(Hash) ? arg.sort : arg
22
+ end
23
+ # what is the configured arity for uniqueness?
24
+ # minus one because zero indexed
25
+ uniqueness_args = args[0..(configuration.arity_for_uniqueness - 1)]
26
+ args = { class: job, args: uniqueness_args }
27
+ key = Digest::MD5.hexdigest Resque.encode(args)
28
+ puts "redis key for uniqueness for #{args} is: #{key.green}"
29
+ key
30
+ rescue => e
31
+ Raven.captureMessage("redis_key error", extra: { signature: payload, error: e.class.to_s, message: e.message })
32
+ raise e
33
+ end
34
+ end
35
+ end
36
+ if configuration.unique_at_runtime
37
+ # The versions of redis_key from resque_solo and resque-lonely_job are incompatible.
38
+ # So we forked resque-lonely_job, change the name of the method so it would not conflict,
39
+ # and now we can override it, and fix the params to be compatible with the redis_key
40
+ # from resque_solo
41
+ # Does not need any customization for arity, because it funnels down to redis_key,
42
+ # and we handle the arity option there
43
+ define_method(:lonely_job_redis_key) do |*args|
44
+ puts "overriding lonely_job_redis_key in #{self}"
45
+ "lonely_job:#{redis_key({"class" => self.to_s, "args" => args})}"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ module Resque
2
+ module UniqueByArity
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'resque/unique_by_arity/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "resque-unique_by_arity"
8
+ spec.version = Resque::UniqueByArity::VERSION
9
+ spec.authors = ["Peter Boling"]
10
+ spec.email = ["peter.boling@gmail.com"]
11
+
12
+ spec.summary = %q{Magic hacks which allow integration of resque_solo and resque-lonely_simlutaneously into Resque jobs}
13
+ spec.description = %q{resque_solo and resque-lonely are incompatible - fixes that}
14
+ spec.homepage = "https://github.com/pboling/resque-unique_by_arity"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_runtime_dependency "resque-lonely_job"
24
+ spec.add_runtime_dependency "resque_solo"
25
+ spec.add_development_dependency "bundler", "~> 1.14"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-unique_by_arity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Boling
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: resque-lonely_job
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: resque_solo
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: resque_solo and resque-lonely are incompatible - fixes that
84
+ email:
85
+ - peter.boling@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
97
+ - bin/setup
98
+ - lib/resque/unique_by_arity.rb
99
+ - lib/resque/unique_by_arity/configuration.rb
100
+ - lib/resque/unique_by_arity/cop.rb
101
+ - lib/resque/unique_by_arity/cop_modulizer.rb
102
+ - lib/resque/unique_by_arity/version.rb
103
+ - resque-unique_by_arity.gemspec
104
+ homepage: https://github.com/pboling/resque-unique_by_arity
105
+ licenses: []
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.6.8
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Magic hacks which allow integration of resque_solo and resque-lonely_simlutaneously
127
+ into Resque jobs
128
+ test_files: []