kungfuig 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7209ee253dbd083df7df4be1c0596cf3be0b45eb
4
- data.tar.gz: 9cb680779c32389e770bceb047b4440c5e39c423
3
+ metadata.gz: d30ca22dee6e6cde7f9f34d17995ff7b27f6b37c
4
+ data.tar.gz: a0b476f59450a277e1ad55f2927240a5689e978a
5
5
  SHA512:
6
- metadata.gz: 37ce51cdf63d82c08b78305427e23b1c6721533e5486bc7416ab9d9f3cf774b5fabf74af09c35b3385f0371a4c5c818c35e07b7f3c180e7c825d4411f93f3846
7
- data.tar.gz: 654e3a115be6951f928a4e56441668eaad7b3f49f224dd3ee5f463a4eb2b5fbfb1c8098c5bb48daeb783c8a5e18132caa16b53b645a6467c872d63a635b5b08e
6
+ metadata.gz: f3a3077967091d00545cce2ccdbff1a76360f51150939374c2e5b402191b0beee12133af44ee5f8debb00390878225b4ac031c7ba964cec776173ae978fb998f
7
+ data.tar.gz: 058f353934143317f307ea99626480ff2f50558880ae25fb4eea2d69ccaaf77a1bf706b02af365cd5078dc714ded18ad0af7b31fd566b4551d806c990fca1a3e
@@ -1,5 +1,10 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ Style/AsciiIdentifiers:
4
+ Exclude:
5
+ - 'lib/**/*'
6
+ - 'spec/**/*'
7
+
3
8
  Style/AsciiComments:
4
9
  Exclude:
5
10
  - 'lib/**/*'
@@ -8,3 +13,8 @@ Style/AsciiComments:
8
13
  Style/RaiseArgs:
9
14
  Exclude:
10
15
  - 'lib/**/*'
16
+
17
+ Style/SpecialGlobalVars:
18
+ Exclude:
19
+ - 'lib/**/*'
20
+ - 'spec/**/*'
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  # spec.metadata['allowed_push_host'] = 'http://mygemserver.com' if spec.respond_to?(:metadata)
23
23
 
24
24
  spec.add_dependency 'hashie', '~> 3'
25
+ spec.add_dependency 'sidekiq', '~> 3.5', '>= 3.5.2'
25
26
 
26
27
  spec.add_development_dependency 'bundler', '~> 1.7'
27
28
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -30,4 +31,6 @@ Gem::Specification.new do |spec|
30
31
  spec.add_development_dependency 'rspec', '~> 2.12'
31
32
  spec.add_development_dependency 'cucumber', '~> 1.3'
32
33
  spec.add_development_dependency 'yard', '~> 0'
34
+
35
+ spec.add_development_dependency 'rspec-sidekiq', '~> 1'
33
36
  end
@@ -1,11 +1,52 @@
1
- require 'kungfuig/version'
2
1
  require 'yaml'
3
2
  require 'hashie'
4
3
 
4
+ require 'kungfuig/version'
5
+ require 'kungfuig/aspector'
6
+
5
7
  module Kungfuig
6
8
  ASPECT_PREFIX = '♻_'.freeze
7
9
  MX = Mutex.new
8
10
 
11
+ # rubocop:disable Style/VariableName
12
+ # rubocop:disable Style/MethodName
13
+ def ✍(receiver, method, result, *args)
14
+ require 'logger'
15
+ @✍ ||= Kernel.const_defined?('Rails') && Rails.logger || Logger.new($stdout)
16
+ message = receiver.is_a?(String) ? "#{receiver} | #{method}" : "#{receiver.class}##{method}"
17
+ "#{message} called with «#{args.inspect}» and returned «#{result || 'nothing (was it before aspect?)'}»".tap do |m|
18
+ @✍.debug m
19
+ end
20
+ end
21
+ module_function :✍
22
+ # rubocop:enable Style/MethodName
23
+ # rubocop:enable Style/VariableName
24
+
25
+ # rubocop:disable Metrics/CyclomaticComplexity
26
+ # rubocop:disable Metrics/MethodLength
27
+ def load_stuff hos
28
+ case hos
29
+ when NilClass then Hashie::Mash.new # aka skip
30
+ when Hash then Hashie::Mash.new(hos)
31
+ when String
32
+ begin
33
+ File.exist?(hos) ? Hashie::Mash.load(hos) : Hashie::Mash.new(YAML.load(hos)).tap do |opts|
34
+ fail ArgumentError.new "#{__callee__} expects valid YAML configuration file or YAML string." unless opts.is_a?(Hash)
35
+ end
36
+ rescue ArgumentError
37
+ fail ArgumentError.new "#{__callee__} expects valid YAML configuration file. [#{hos}] contains invalid syntax."
38
+ rescue Psych::SyntaxError
39
+ fail ArgumentError.new "#{__callee__} expects valid YAML configuration string. Got:\n#{hos}"
40
+ end
41
+ when ->(h) { h.respond_to?(:to_hash) } then Hashie::Mash.new(h.to_hash)
42
+ else
43
+ fail ArgumentError.new "#{__callee__} accepts either String or Hash as parameter."
44
+ end
45
+ end
46
+ # rubocop:enable Metrics/MethodLength
47
+ # rubocop:enable Metrics/CyclomaticComplexity
48
+ module_function :load_stuff
49
+
9
50
  module InstanceMethods
10
51
  # Configures everything by hash or yaml from string or file. Whether code block
11
52
  # is passed, it is processed with @options instance.
@@ -64,34 +105,12 @@ module Kungfuig
64
105
  !option(*keys).nil?
65
106
  end
66
107
 
67
- # rubocop:disable Metrics/AbcSize
68
- # rubocop:disable Metrics/CyclomaticComplexity
69
- # rubocop:disable Metrics/MethodLength
70
108
  # @param hos [Hash|String] the new values taken from hash,
71
109
  # mash or string (when string, should be either valid YAML file name or
72
110
  # string with valid YAML)
73
111
  def merge_hash_or_string! hos
74
- options.deep_merge! case hos
75
- when NilClass then Hashie::Mash.new # aka skip
76
- when Hash then Hashie::Mash.new(hos)
77
- when String
78
- begin
79
- File.exist?(hos) ? Hashie::Mash.load(hos) : Hashie::Mash.new(YAML.load(hos)).tap do |opts|
80
- fail ArgumentError.new "#{__callee__} expects valid YAML configuration file or YAML string." unless opts.is_a?(Hash)
81
- end
82
- rescue ArgumentError
83
- fail ArgumentError.new "#{__callee__} expects valid YAML configuration file. [#{hos}] contains invalid syntax."
84
- rescue Psych::SyntaxError
85
- fail ArgumentError.new "#{__callee__} expects valid YAML configuration string. Got:\n#{hos}"
86
- end
87
- when ->(h) { h.respond_to?(:to_hash) } then Hashie::Mash.new(h.to_hash)
88
- else
89
- fail ArgumentError.new "#{__callee__} accepts either String or Hash as parameter."
90
- end
112
+ options.deep_merge! Kungfuig.load_stuff hos
91
113
  end
92
- # rubocop:enable Metrics/MethodLength
93
- # rubocop:enable Metrics/CyclomaticComplexity
94
- # rubocop:enable Metrics/AbcSize
95
114
  private :merge_hash_or_string!
96
115
  end
97
116
 
@@ -126,15 +145,15 @@ module Kungfuig
126
145
 
127
146
  unless instance_methods.include?(:"#{ASPECT_PREFIX}#{meth}")
128
147
  class_eval <<-CODE
129
- alias_method :#{ASPECT_PREFIX}#{meth}, :#{meth}
148
+ alias_method :'#{ASPECT_PREFIX}#{meth}', :'#{meth}'
130
149
  def #{meth}(*args, &cb)
131
- ps = self.class.aspects(:#{meth}).merge((class << self; self; end).aspects(:#{meth})) { |_, c, ec| c | ec }
150
+ ps = self.class.aspects(:'#{meth}').merge((class << self; self; end).aspects(:'#{meth}')) { |_, c, ec| c | ec }
132
151
  ps[:before].each do |p|
133
- p.call(*args) # TODO: make prependers able to change args!!!
152
+ p.call(self, :'#{meth}', nil, *args) # FIXME: allow argument modification!!!
134
153
  end
135
- send(:#{ASPECT_PREFIX}#{meth}, *args, &cb).tap do |result|
154
+ send(:'#{ASPECT_PREFIX}#{meth}', *args, &cb).tap do |result|
136
155
  ps[:after].each do |p|
137
- p.call result, *args
156
+ p.call(self, :'#{meth}', result, *args)
138
157
  end
139
158
  end
140
159
  end
@@ -1,5 +1,3 @@
1
- require_relative '../kungfuig'
2
-
3
1
  module Kungfuig
4
2
  # Generic helper for massive attaching aspects
5
3
  module Aspector
@@ -10,26 +8,45 @@ module Kungfuig
10
8
  v = [*v].map(&:to_sym)
11
9
  case
12
10
  when v.empty? then []
13
- when v.include?(:'*') then klazz.instance_methods(false)
11
+ when v.include?('*'), v.include?(:'*') then klazz.instance_methods(false)
14
12
  else klazz.instance_methods & v
15
13
  end
16
14
  end.reduce(&:-)
17
15
  end
16
+
17
+ def remap_hash_for_easy_iteration hash
18
+ hash = hash.each_with_object(Hashie::Mash.new) do |(k, v), memo|
19
+ v.each { |m, c| memo.public_send("#{m}!")[k] = c }
20
+ end unless (hash.keys - %w(before after exclude)).empty?
21
+ hash.each_with_object({}) do |(k, v), memo|
22
+ v.each { |m, h| ((memo[h] ||= {})[k.to_sym] ||= []) << m }
23
+ end
24
+ end
25
+
26
+ def proc_instance string
27
+ m, k = string.split('#').reverse
28
+ (k ? Kernel.const_get(k).method(m) : method(m)).to_proc
29
+ end
18
30
  end
19
31
 
20
32
  def attach(to, before: nil, after: nil, exclude: nil)
21
- raise ArgumentError, "Trying to attach nothing to #{klazz}. I need a block!" unless block_given?
22
-
23
- klazz = to.is_a?(Class) ? to : class << to; self; end # attach to klazz’s eigenclass if object given
33
+ klazz = case to
34
+ when String then Kernel.const_get(to) # we are ready to get a class name
35
+ when Class then to # got a class! wow, somebody has the documentation read
36
+ else class << to; self; end # attach to klazz’s eigenclass if object given
37
+ end
24
38
 
39
+ raise ArgumentError, "Trying to attach nothing to #{klazz}##{to}. I need a block!" unless block_given?
25
40
  klazz.send(:include, Kungfuig::Aspector) unless klazz.ancestors.include? Kungfuig::Aspector
26
41
  cb = Proc.new
27
42
 
28
43
  H.new.value_to_method_list(klazz, before, exclude).each do |m|
44
+ # FIXME: log methods that failed to be wrapped more accurately? # Kungfuig.✍(klazz, m, e.inspect)
29
45
  klazz.aspect(m, false, &cb)
30
46
  end unless before.nil?
31
47
 
32
48
  H.new.value_to_method_list(klazz, after, exclude).each do |m|
49
+ # FIXME: log methods that failed to be wrapped more accurately? # Kungfuig.✍(klazz, m, e.inspect)
33
50
  klazz.aspect(m, true, &cb)
34
51
  end unless after.nil?
35
52
 
@@ -37,6 +54,31 @@ module Kungfuig
37
54
  end
38
55
  module_function :attach
39
56
 
57
+ # 'Test':
58
+ # after:
59
+ # 'yo': 'YoCalledAsyncHandler#process'
60
+ # 'yo1' : 'YoCalledAsyncHandler#process'
61
+ # before:
62
+ # 'yo': 'YoCalledAsyncHandler#process'
63
+ def bulk(hos)
64
+ Kungfuig.load_stuff(hos).map do |klazz, hash|
65
+ next if hash.empty?
66
+ [klazz, H.new.remap_hash_for_easy_iteration(hash).map do |handler, methods|
67
+ begin
68
+ attach(klazz, **methods, &H.new.proc_instance(handler))
69
+ rescue => e
70
+ raise ArgumentError, [
71
+ "Bad input to Kungfuig::Aspector##{__callee__}.",
72
+ "Args: #{methods.inspect}",
73
+ "Original exception: “#{e.message}”.",
74
+ e.backtrace.unshift("Backtrace:").join("#{$/}⮩ ")
75
+ ].join($/.to_s)
76
+ end
77
+ end]
78
+ end.compact.to_h
79
+ end
80
+ module_function :bulk
81
+
40
82
  private_constant :H
41
83
  end
42
84
  end
@@ -0,0 +1,41 @@
1
+ require_relative './aspector'
2
+ require 'rubygems/exceptions'
3
+
4
+ begin
5
+ require 'sidekiq'
6
+ raise LoadError.new unless Kernel.const_defined?('Sidekiq')
7
+ rescue LoadError
8
+ raise(Gem::DependencyError, "Sidekiq id required to use this functionality!")
9
+ end
10
+
11
+ module Kungfuig
12
+ # Generic helper for massive attaching aspects
13
+ class Jobber
14
+ class << self
15
+ # 'Test':
16
+ # '*': 'YoJob'
17
+ def bulk(hos)
18
+ @hash = Kungfuig.load_stuff hos
19
+ Kungfuig::Aspector.bulk(
20
+ @hash.map do |klazz, hash|
21
+ [klazz, { after: hash.map { |k, _| [k, 'Kungfuig::Jobber#bottleneck'] }.to_h }]
22
+ end.to_h
23
+ )
24
+ end
25
+
26
+ def bottleneck(receiver, method, result, *args)
27
+ respond_to = ->(m, r) { r.respond_to? m.to_sym }
28
+ r = case receiver
29
+ when respond_to.curry[:to_hash] then receiver.to_hash
30
+ when respond_to.curry[:to_h] then receiver.to_h
31
+ else receiver
32
+ end
33
+
34
+ Kernel.const_get(@hash[receiver.class.name][method])
35
+ .perform_async(r, method, result, *args)
36
+ rescue => e
37
+ Kungfuig.✍("Fail [#{e.message}] while #{receiver}", method, result, *args)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Kungfuig
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kungfuig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kantox LTD
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-23 00:00:00.000000000 Z
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -24,6 +24,26 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sidekiq
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.5'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 3.5.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.5'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.5.2
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: bundler
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +128,20 @@ dependencies:
108
128
  - - "~>"
109
129
  - !ruby/object:Gem::Version
110
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rspec-sidekiq
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '1'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '1'
111
145
  description: Config with goodnesses.
112
146
  email:
113
147
  - aleksei.matiushkin@kantox.com
@@ -126,6 +160,7 @@ files:
126
160
  - kungfuig.gemspec
127
161
  - lib/kungfuig.rb
128
162
  - lib/kungfuig/aspector.rb
163
+ - lib/kungfuig/jobber.rb
129
164
  - lib/kungfuig/version.rb
130
165
  homepage: http://kantox.com
131
166
  licenses: