faktory_worker_ruby 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 601942270c2185c3d6950e04d9cffcfa03256689
4
+ data.tar.gz: 51254887f57c7338d086ff07a7e76e9b511fcc53
5
+ SHA512:
6
+ metadata.gz: 8f22aa99ebfa7d4e79d4b3157561cc14716355716e257c05252539b2ef23ce811f7531d2802722629905427a83e6670c934d8eab977bde9e8bc93737db65ca46
7
+ data.tar.gz: b0e723333032496197fd07a5a90441836885d2fb408860e0292a354abbb89d043aca27cfba4ad4d592d1225def1a5e24e7ff747405834cd5448ad417cd04bd1b
@@ -0,0 +1,50 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ faktory_worker_ruby (0.5.0)
5
+ connection_pool (~> 2.2, >= 2.2.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ connection_pool (2.2.1)
11
+ minitest (5.10.3)
12
+ minitest-hooks (1.4.2)
13
+ rake (12.1.0)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ faktory_worker_ruby!
20
+ minitest (~> 5)
21
+ minitest-hooks
22
+ rake (~> 12)
23
+
24
+ BUNDLED WITH
25
+ 1.15.4
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
@@ -0,0 +1,91 @@
1
+ # faktory\_worker\_ruby
2
+
3
+ Faktory\_worker\_ruby is the official Ruby client and worker process for the
4
+ Faktory background job server. It is similar to [Sidekiq](http://sidekiq.org).
5
+
6
+ ```
7
+ +--------------------+
8
+ | |
9
+ | Faktory |
10
+ | Server |
11
+ +---------->>>>| +>>>>--------+
12
+ | | | |
13
+ | | | |
14
+ | +--------------------+ |
15
+ +-----------------+ +-------------------+
16
+ | | | |
17
+ | Client | | Worker |
18
+ | pushes | | pulls |
19
+ | jobs | | jobs |
20
+ | | | |
21
+ | | | |
22
+ +-----------------+ +-------------------+
23
+ ```
24
+
25
+ * Client - an API any process can use to push jobs to the Faktory server.
26
+ * Worker - a process that pulls jobs from Faktory and executes them.
27
+ * Server - the Faktory daemon which stores background jobs in
28
+ queues to be processed by Workers.
29
+
30
+ This gem contains only the client and worker parts. The
31
+ server part is [here](https://github.com/contribsys/faktory/)
32
+
33
+ ## Installation
34
+
35
+ First, make sure you have the [Faktory server](https://github.com/contribsys/faktory/#installation) installed.
36
+
37
+ Next, install this gem:
38
+
39
+ gem install faktory_worker_ruby
40
+
41
+ ## Your First Job
42
+
43
+ Your Jobs should include the Faktory::Job module and have a `perform`
44
+ method.
45
+
46
+ ```ruby
47
+ class SomeJob
48
+ include Faktory::Job
49
+
50
+ def perform(...)
51
+ end
52
+ end
53
+ ```
54
+
55
+ then just call `SomeJob.perform_async(...)` to create a job.
56
+
57
+ Arguments to the perform method must be simple types supported
58
+ by JSON, exactly like Sidekiq.
59
+
60
+ ## Start the worker
61
+
62
+ Once you've created a job, you need to start a Worker process to execute
63
+ those jobs.
64
+
65
+ ```ruby
66
+ bundle exec faktory-worker
67
+ ```
68
+
69
+ ## Why not Sidekiq?
70
+
71
+ Sidekiq is awesome; it's stable and useful. It suffers from two design limitations:
72
+
73
+ 1. Sidekiq uses Redis and Redis is dumb datastore, all Sidekiq features are
74
+ implemented in Ruby and have to travel over the network to access data.
75
+ 2. Because of (1), Sidekiq is limited to Ruby. You can't execute jobs
76
+ with, e.g., Python and get the same Sidekiq features.
77
+
78
+ Instead Faktory is a "smart" server that implements all major features
79
+ within the server itself; the worker process can be dumb and rely on
80
+ the server for job retries, reservation, Web UI, etc. This also means
81
+ we can create workers in any programming language.
82
+
83
+ If your organization is 100% Ruby, Sidekiq will serve you well. If your
84
+ organization is polyglot, Faktory will be a better fit.
85
+
86
+ faktory\_worker\_ruby tries to be Sidekiq API compatible where possible (and
87
+ PRs to improve this are very welcome).
88
+
89
+ ## Author
90
+
91
+ Mike Perham, @mperham, mike @ contribsys.com
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs += ["test"]
6
+ test.warning = true
7
+ test.pattern = 'test/**/*_test.rb'
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Quiet some warnings we see when running in warning mode:
4
+ # RUBYOPT=-w bundle exec faktory
5
+ $TESTING = false
6
+
7
+ require_relative '../lib/faktory/cli'
8
+
9
+ begin
10
+ cli = Faktory::CLI.instance
11
+ cli.parse
12
+ cli.run
13
+ rescue => e
14
+ raise e if $DEBUG
15
+ STDERR.puts e.message
16
+ STDERR.puts e.backtrace.join("\n")
17
+ exit 1
18
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/faktory/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "faktory_worker_ruby"
6
+ gem.authors = ["Mike Perham"]
7
+ gem.email = ["mike@contribsys.com"]
8
+ gem.summary = "Ruby worker for Faktory"
9
+ gem.description = "Ruby worker for Faktory."
10
+ gem.homepage = "http://contribsys.com"
11
+ gem.license = "LGPL-3.0"
12
+
13
+ gem.executables = ['faktory-worker']
14
+ gem.files = `git ls-files | grep -Ev '^(test|myapp|examples)'`.split("\n")
15
+ gem.test_files = []
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Faktory::VERSION
18
+ gem.required_ruby_version = ">= 2.2.2"
19
+
20
+ gem.add_dependency 'connection_pool', '~> 2.2', ">= 2.2.1"
21
+ gem.add_development_dependency 'minitest', '~> 5'
22
+ gem.add_development_dependency 'minitest-hooks'
23
+ gem.add_development_dependency 'rake', '~> 12'
24
+ end
@@ -0,0 +1,166 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'faktory/version'
4
+
5
+ require 'faktory/logging'
6
+ require 'faktory/client'
7
+ require 'faktory/middleware/chain'
8
+ require 'faktory/job'
9
+ require 'faktory/connection'
10
+
11
+ require 'json'
12
+
13
+ module Faktory
14
+ NAME = 'Faktory'.freeze
15
+ LICENSE = 'See LICENSE and the LGPL-3.0 for licensing details.'
16
+
17
+ DEFAULTS = {
18
+ queues: ['default'],
19
+ concurrency: 10,
20
+ require: '.',
21
+ environment: 'development',
22
+ # As of 2017, Heroku's process timeout is 30 seconds.
23
+ # After 30 seconds, processes are KILLed so assume 25
24
+ # seconds to gracefully shutdown and 5 seconds to hard
25
+ # shutdown.
26
+ timeout: 25,
27
+ error_handlers: [],
28
+ lifecycle_events: {
29
+ startup: [],
30
+ quiet: [],
31
+ shutdown: [],
32
+ },
33
+ reloader: proc { |&block| block.call },
34
+ }
35
+
36
+ DEFAULT_JOB_OPTIONS = {
37
+ 'retry' => 25,
38
+ 'queue' => 'default'
39
+ }
40
+
41
+ def self.options
42
+ @options ||= DEFAULTS.dup
43
+ end
44
+ def self.options=(opts)
45
+ @options = opts
46
+ end
47
+
48
+ ##
49
+ # Configuration for Faktory executor, use like:
50
+ #
51
+ # Faktory.configure_worker do |config|
52
+ # config.worker_middleware do |chain|
53
+ # chain.add MyServerHook
54
+ # end
55
+ # end
56
+ def self.configure_worker
57
+ yield self if worker?
58
+ end
59
+
60
+ ##
61
+ # Configuration for Faktory client, use like:
62
+ #
63
+ # Faktory.configure_client do |config|
64
+ # config.faktory = { :size => 1, :url => 'myhost:7419' }
65
+ # end
66
+ def self.configure_client
67
+ yield self unless worker?
68
+ end
69
+
70
+ def self.worker?
71
+ defined?(Faktory::CLI)
72
+ end
73
+
74
+ def self.server
75
+ raise ArgumentError, "requires a block" unless block_given?
76
+ server_pool.with do |conn|
77
+ yield conn
78
+ end
79
+ end
80
+
81
+ def self.server_pool
82
+ @pool ||= Faktory::Connection.create
83
+ end
84
+
85
+ def self.faktory=(hash)
86
+ @pool = Faktory::Connection.create(hash)
87
+ end
88
+
89
+ def self.client_middleware
90
+ @client_chain ||= Middleware::Chain.new
91
+ yield @client_chain if block_given?
92
+ @client_chain
93
+ end
94
+
95
+ def self.worker_middleware
96
+ @worker_chain ||= Middleware::Chain.new
97
+ yield @worker_chain if block_given?
98
+ @worker_chain
99
+ end
100
+
101
+ def self.default_job_options=(hash)
102
+ # stringify
103
+ @default_job_options = default_job_options.merge(Hash[hash.map{|k, v| [k.to_s, v]}])
104
+ end
105
+ def self.default_job_options
106
+ defined?(@default_job_options) ? @default_job_options : DEFAULT_JOB_OPTIONS
107
+ end
108
+
109
+ def self.load_json(string)
110
+ JSON.parse(string)
111
+ end
112
+ def self.dump_json(object)
113
+ JSON.generate(object)
114
+ end
115
+
116
+ def self.logger
117
+ Faktory::Logging.logger
118
+ end
119
+ def self.logger=(log)
120
+ Faktory::Logging.logger = log
121
+ end
122
+
123
+ def self.💃🕺(io = $stdout)
124
+ colors = (31..37).to_a
125
+ sz = colors.size
126
+ "DANCE MODE ACTIVATED".chars.each_with_index do |chr, idx|
127
+ io.print("\e[#{colors[rand(sz)]};1m#{chr}")
128
+ end
129
+ io.print("\e[0m\n")
130
+ end
131
+
132
+ # Register a proc to handle any error which occurs within the Faktory process.
133
+ #
134
+ # Faktory.configure_worker do |config|
135
+ # config.error_handlers << proc {|ex,ctx_hash| MyErrorService.notify(ex, ctx_hash) }
136
+ # end
137
+ #
138
+ # The default error handler logs errors to Faktory.logger.
139
+ def self.error_handlers
140
+ self.options[:error_handlers]
141
+ end
142
+
143
+ # Register a block to run at a point in the Faktory lifecycle.
144
+ # :startup, :quiet or :shutdown are valid events.
145
+ #
146
+ # Faktory.configure_worker do |config|
147
+ # config.on(:shutdown) do
148
+ # puts "Goodbye cruel world!"
149
+ # end
150
+ # end
151
+ def self.on(event, &block)
152
+ raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
153
+ raise ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
154
+ options[:lifecycle_events][event] << block
155
+ end
156
+
157
+ # We are shutting down Faktory but what about workers that
158
+ # are working on some long job? This error is
159
+ # raised in workers that have not finished within the hard
160
+ # timeout limit. This is needed to rollback db transactions,
161
+ # otherwise Ruby's Thread#kill will commit.
162
+ # DO NOT RESCUE THIS ERROR IN YOUR WORKERS
163
+ class Shutdown < Interrupt; end
164
+ end
165
+
166
+ require 'faktory/rails' if defined?(::Rails::Engine)