aservice 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 79bff4730e2fb2c8fa887a439ea31957acc798528dd751d0b2ef129f424dd004
4
+ data.tar.gz: 340923d749844cfdb527b4935856b58761544da946af1c478e0635b9d0a372ef
5
+ SHA512:
6
+ metadata.gz: 58514c9c2ebf6b153c4657a8fb00625fc27ee3570b326acbe773b511a73a731acae4af277995b65cb93723d00dc12ef104c908dd9dcbede078c2fa98a996b457
7
+ data.tar.gz: e8706e954ba0be5e5dfdca059d6b3996224c43e8a2bf474c58a1854b33d78481b0116f5636adb28132267d4ece6d1b7ee8aae809449eac73cc12c9f3cd40816b
@@ -0,0 +1,7 @@
1
+ /.bundle/
2
+ /Gemfile.lock
3
+ /coverage/
4
+ /pkg/
5
+ /spec/reports/
6
+ /tmp/
7
+ /examples/config.ru
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1,39 @@
1
+
2
+ AllCops:
3
+ TargetRubyVersion: 2.5
4
+ Include:
5
+ - "lib/**/*.rb"
6
+ - "spec/**/*.rb"
7
+ Exclude:
8
+ - "bin/**/*"
9
+ - "examples/*"
10
+ - "spec/support/*"
11
+ - "Gemfile"
12
+ - "Rakefile"
13
+ - "*.gemspec"
14
+ DisplayCopNames: true
15
+ StyleGuideCopsOnly: false
16
+
17
+ Style/MethodMissingSuper:
18
+ Enabled: false
19
+
20
+ Style/Documentation:
21
+ Exclude:
22
+ - "spec/**/*.rb"
23
+
24
+ Style/BlockDelimiters:
25
+ Exclude:
26
+ - "spec/**/*.rb"
27
+
28
+ Metrics/MethodLength:
29
+ Exclude:
30
+ - "spec/**/*.rb"
31
+
32
+ Layout/LineLength:
33
+ Max: 120
34
+ Exclude:
35
+ - "spec/**/*.rb"
36
+
37
+ Metrics/BlockLength:
38
+ Exclude:
39
+ - "spec/**/*.rb"
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,7 @@
1
+ Aservice gem allow you to execute your services in background as a sidekiq jod.
2
+
3
+ Include Aservice into your class and [method_name]_async and [method_name]_after will be available.
4
+
5
+ [method_name]_async call method in sidekiq background job.
6
+ And [method_name]_after accepts sidekiq job as a first argument and would call method only when job will be successfully completed.
7
+ Check examples folder for example
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'aservice'
5
+ s.version = '0.0.2'
6
+ s.date = '2020-07-07'
7
+ s.summary = 'Aservice'
8
+ s.description = 'Gem for running services asynchroniously'
9
+ s.authors = ['Aleksandr Korotkikh']
10
+ s.email = 'koralvas@gmail.com'
11
+ s.homepage =
12
+ 'https://github.com/SanderMander/aservice'
13
+ s.license = 'MIT'
14
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
15
+ f.match(%r{^(spec|examples)/})
16
+ end
17
+ s.require_paths = ['lib']
18
+ s.add_development_dependency 'bundler', '~> 2'
19
+ s.add_development_dependency 'pry-byebug'
20
+ s.add_development_dependency 'rake', '>= 12.3.3'
21
+ s.add_development_dependency 'rspec', '~> 3.0'
22
+ s.add_development_dependency 'rubocop'
23
+ s.add_dependency 'anyway_config', '>= 2.0.0'
24
+ s.add_dependency('sidekiq', ['>= 4.2.1'])
25
+ s.add_dependency('sidekiq-status', ['>= 1.1.4'])
26
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sidekiq'
4
+ require 'sidekiq-status'
5
+ require 'anyway_config'
6
+ require_relative 'aservice/config.rb'
7
+ require_relative 'aservice/worker/worker.rb'
8
+ require_relative 'aservice/worker/aservice_worker.rb'
9
+ require_relative 'aservice/callback.rb'
10
+ require_relative 'sidekiq/middleware/callback_middleware.rb'
11
+
12
+ # Main mixin which provide Asynchronious service call
13
+ module Aservice
14
+ def self.included(base)
15
+ base.class_eval do
16
+ extend ClassMethods
17
+ end
18
+ end
19
+
20
+ # Class methods for service.
21
+ module ClassMethods
22
+ def call_async(*args)
23
+ perform(:async, 'call', args)
24
+ end
25
+
26
+ def call_after(jid, *args)
27
+ args = [] if args.nil?
28
+ perform(:after, 'call', args.unshift(jid))
29
+ end
30
+
31
+ def respond_to_missing?(method, _)
32
+ return false if method =~ /_(async|after)$/
33
+ end
34
+
35
+ def method_missing(method, *args)
36
+ method = method.to_s
37
+ if method =~ /_async$/
38
+ method = method.sub(/.*\K_async/, '')
39
+ perform(:async, method, args)
40
+ elsif method =~ /_after$/
41
+ method = method.sub(/.*\K_after/, '')
42
+ perform(:after, method, args)
43
+ else
44
+ raise_no_method_error("No method: #{method} for class: #{AserviceWorker.name}")
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def perform(type, method, args)
51
+ worker = AserviceWorker.set(queue: Aservice::Config.queue)
52
+ raise_no_method_error("No method: #{method} for class: #{name}") unless respond_to?(method.to_sym)
53
+ return worker.perform_async(name, method, *args) if type == :async
54
+
55
+ jid = args.shift
56
+ if Sidekiq::Status.complete?(jid)
57
+ worker.perform_async(name, method, *args)
58
+ else
59
+ worker.perform_after(jid, name, method, *args)
60
+ end
61
+ end
62
+
63
+ def raise_no_method_error(msg)
64
+ raise NoMethodError, msg
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aservice
4
+ # Sidekiq job callbacks
5
+ class Callback
6
+ class << self
7
+ def add(jid, class_name, method, args)
8
+ opt = {
9
+ 'class' => class_name,
10
+ 'method' => method,
11
+ 'args' => args
12
+ }
13
+ Sidekiq.redis do |conn|
14
+ conn.multi do
15
+ conn.rpush(key(jid), opt.to_json)
16
+ conn.expire(key(jid), Aservice::Config.callbacks_expiration)
17
+ end
18
+ end
19
+ end
20
+
21
+ def success(job)
22
+ while (opt = pop_next(job['jid']))
23
+ execute_service(opt['class'], opt['method'], opt['args'])
24
+ end
25
+ end
26
+
27
+ def failure(job)
28
+ clear_stack(job['jid'])
29
+ end
30
+
31
+ private
32
+
33
+ def execute_service(class_name, method, args)
34
+ Kernel.const_get(class_name).send(method, *args)
35
+ end
36
+
37
+ def pop_next(jid)
38
+ opt = Sidekiq.redis do |conn|
39
+ conn.lpop(key(jid))
40
+ end
41
+ return false if opt.nil?
42
+
43
+ JSON.parse(opt)
44
+ end
45
+
46
+ def clear_stack(jid)
47
+ Sidekiq.redis do |conn|
48
+ conn.del(key(jid))
49
+ end
50
+ end
51
+
52
+ def key(jid)
53
+ "#{Aservice::Config.redis_prefix}_#{jid}"
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aservice
4
+ # anyway config wrapper
5
+ class Config < Anyway::Config
6
+ config_name :aservice
7
+
8
+ attr_config logger: Logger.new($stdout),
9
+ severity: Logger::Severity::DEBUG,
10
+ queue: 'default',
11
+ status_expiration: 60 * 30,
12
+ redis_prefix: 'AC',
13
+ callbacks_expiration: 60 * 30
14
+ def self.instance
15
+ @config ||= new
16
+ yield @config if block_given?
17
+ @config
18
+ end
19
+
20
+ def self.respond_to_missing?(_name, _)
21
+ instance.respond_to?(method)
22
+ end
23
+
24
+ def self.method_missing(method)
25
+ instance.send(method)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # sidekiq worker which run services in background
4
+ class AserviceWorker
5
+ include Aservice::Worker
6
+
7
+ def perform(class_name, method_name, *args)
8
+ Kernel.const_get(class_name).__send__(method_name, *args)
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aservice
4
+ # Mixin which define perform_after method
5
+ module Worker
6
+ def self.included(base)
7
+ base.include Sidekiq::Worker
8
+ base.include Sidekiq::Status::Worker
9
+ Sidekiq::Worker::Setter.class_eval do
10
+ def perform_after(jid, class_name, method, *args)
11
+ Aservice::Callback.add(jid, class_name, method, args)
12
+ end
13
+ end
14
+
15
+ def expiration
16
+ Aservice::Config.status_expiration
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sidekiq
4
+ module Middleware
5
+ # Middleware which executes callbacks
6
+ class CallbackMiddleware
7
+ def call(_worker_class, job, _queue)
8
+ yield
9
+ Aservice::Callback.success(job)
10
+ rescue StandardError => e
11
+ Aservice::Callback.failure(job)
12
+ raise e
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ Sidekiq.configure_client do |config|
19
+ Sidekiq::Status.configure_client_middleware config
20
+ end
21
+
22
+ Sidekiq.configure_server do |config|
23
+ Sidekiq::Status.configure_server_middleware config
24
+ Sidekiq::Status.configure_client_middleware config
25
+ config.server_middleware do |chain|
26
+ chain.add Sidekiq::Middleware::CallbackMiddleware
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aservice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Aleksandr Korotkikh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry-byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
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: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 12.3.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 12.3.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: anyway_config
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: sidekiq
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 4.2.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 4.2.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: sidekiq-status
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 1.1.4
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 1.1.4
125
+ description: Gem for running services asynchroniously
126
+ email: koralvas@gmail.com
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - ".gitignore"
132
+ - ".rspec"
133
+ - ".rubocop.yml"
134
+ - Gemfile
135
+ - README.md
136
+ - aservice.gemspec
137
+ - lib/aservice.rb
138
+ - lib/aservice/callback.rb
139
+ - lib/aservice/config.rb
140
+ - lib/aservice/worker/aservice_worker.rb
141
+ - lib/aservice/worker/worker.rb
142
+ - lib/sidekiq/middleware/callback_middleware.rb
143
+ homepage: https://github.com/SanderMander/aservice
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubygems_version: 3.0.6
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: Aservice
166
+ test_files: []