aservice 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []