norton 0.1.2 → 0.1.3

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: 45ea8d2f8971be12351a0cd129ed8a851f2a7823
4
- data.tar.gz: bd77674e841f9dd8c8e2603a46b75a4cf03ed281
3
+ metadata.gz: 9fe66b21646e48209504891cdab86b5ac24e1474
4
+ data.tar.gz: cc4d1eaed607c0f71510d38be5dbfeb641a39c0d
5
5
  SHA512:
6
- metadata.gz: 1c4ca36139885b6ea121edc8c3b9ceb81ace3f9abe2c85e01f17c208f280748ef91cfc27b7f7d473e1fd4ca03cd79566193cf99e5e0b20de2273494212dce75f
7
- data.tar.gz: 8e9c450ff7fc10a7d9c8007645ab60640f0be59549c2d952bd286e9babdfe023d3ad076fcf3ac46c27e9e993f6ab061b6cecdd02d693792dd0d9277aeb483fc0
6
+ metadata.gz: 459c0f017e79c424e3861f466667d16942bc980894a54877132a762084c51de66a1ea17a6256eb25e4b55645812454d8cd26ac52f3cda459f0204bbfe9298a95
7
+ data.tar.gz: aed208fccde64fc567af602d48faa093f4b782c280106c88b0ff5e5c5bd3068e209ab4ecce60788dd4d4ea6e8a23eb73162346764b4ac1e25ff4701568879e49
@@ -6,7 +6,6 @@ require "norton/version"
6
6
  require "norton/helper"
7
7
  require "norton/timestamp"
8
8
  require "norton/counter"
9
- require "norton/timed_value"
10
9
  require "norton/objects/hash"
11
10
  require "norton/hash_map"
12
11
 
@@ -17,24 +16,42 @@ module Norton
17
16
  class InvalidType < StandardError; end
18
17
 
19
18
  class << self
19
+ attr_accessor :pools
20
20
  attr_accessor :redis
21
21
 
22
+ def pools
23
+ @pools ||= {}
24
+ end
25
+
22
26
  #
23
27
  # Setup your redis connection.
28
+ #
24
29
  # @param options={} [Hash] [Redis connection configuration]
25
30
  # url - Redis connection url
26
31
  # pool - Connection pool size
27
32
  # timeout - Connection pool timeout
28
- # @return [nil] [description]
29
- def setup(options={})
30
- pool_size = (options[:pool] || 1).to_i
31
- timeout = (options[:timeout] || 2).to_i
33
+ #
34
+ # @example
35
+ # {
36
+ # "default" => { "url" => "redis://localhost:6379/0", "pool" => 4, "timeout" => 2 },
37
+ # "norton2" => { "url" => "redis://localhost:6379/3", "pool" => 4, "timeout" => 2 }
38
+ # }
39
+ #
40
+ # @return [Void]
41
+ #
42
+ def setup(options = {})
43
+ self.pools = {}
44
+ options.deep_symbolize_keys!
32
45
 
33
- Norton.redis = ConnectionPool.new(:size => pool_size, :timeout => timeout) do
34
- Redis.new(
35
- options.slice(:url, :host, :port, :db, :path, :password, :namespace, :ssl_params, :driver)
36
- )
46
+ options.each do |name, conn_params|
47
+ pool_size = (conn_params.delete(:pool) || 1).to_i
48
+ timeout = (conn_params.delete(:timeout) || 2).to_i
49
+ Norton.pools[name] = ConnectionPool.new(size: pool_size, timeout: timeout) do
50
+ Redis.new(conn_params)
51
+ end
37
52
  end
53
+
54
+ Norton.redis = Norton.pools[:default]
38
55
  end
39
56
 
40
57
  # 批量获取多个对象的多个 Norton 字段, 仅仅支持 counter / timestamp
@@ -47,15 +64,22 @@ module Norton
47
64
  # @return [Array] 一组对象
48
65
  #
49
66
  def mget(objects, fields)
50
- keys = objects.flat_map do |object|
51
- fields.map { |f| object.norton_value_key(f) }
67
+ pools_with_name = fields.each_with_object({}) do |name, hash|
68
+ pool = objects[0].class.norton_value_redis_pool(name)
69
+ hash[pool] ||= []
70
+ hash[pool] << name
52
71
  end
53
- nested_values = Norton.redis.with do |conn|
54
- conn.mget(keys)
55
- end.each_slice(fields.size)
56
72
 
57
- objects.zip(nested_values).each do |object, values|
58
- object.send(:assign_values, fields.zip(values).to_h)
73
+ pools_with_name.each do |pool, names|
74
+ keys = objects.flat_map do |object|
75
+ names.map { |name| object.norton_value_key(name) }
76
+ end
77
+ nested_values = pool.with do |conn|
78
+ conn.mget(keys)
79
+ end.each_slice(names.size)
80
+ objects.zip(nested_values).each do |object, values|
81
+ object.send(:assign_values, names.zip(values).to_h)
82
+ end
59
83
  end
60
84
 
61
85
  objects
@@ -16,11 +16,12 @@ module Norton
16
16
  # @return [type] [description]
17
17
  def counter(name, options={}, &blk)
18
18
  register_norton_value(name, :counter, options)
19
+ redis = norton_value_redis_pool(name)
19
20
 
20
21
  # Redis: GET
21
22
  define_method(name) do
22
23
  instance_variable_get("@#{name}") || begin
23
- value = Norton.redis.with do |conn|
24
+ value = redis.with do |conn|
24
25
  conn.get(norton_value_key(name))
25
26
  end || send("#{name}_default_value")
26
27
  instance_variable_set("@#{name}", value.to_i)
@@ -29,7 +30,7 @@ module Norton
29
30
 
30
31
  # Redis: SET
31
32
  define_method("#{name}=") do |value|
32
- if Norton.redis.with { |conn| conn.set(norton_value_key(name), value) }
33
+ if redis.with { |conn| conn.set(norton_value_key(name), value) }
33
34
  instance_variable_set("@#{name}", value.to_i)
34
35
  end
35
36
  end
@@ -40,7 +41,7 @@ module Norton
40
41
 
41
42
  # Redis: INCR
42
43
  define_method("incr_#{name}") do
43
- value = Norton.redis.with do |conn|
44
+ value = redis.with do |conn|
44
45
  conn.incr(norton_value_key(name))
45
46
  end
46
47
  instance_variable_set("@#{name}", value.to_i)
@@ -48,7 +49,7 @@ module Norton
48
49
 
49
50
  # Redis: DECR
50
51
  define_method("decr_#{name}") do
51
- value = Norton.redis.with do |conn|
52
+ value = redis.with do |conn|
52
53
  conn.decr(norton_value_key(name))
53
54
  end
54
55
  instance_variable_set("@#{name}", value.to_i)
@@ -56,7 +57,7 @@ module Norton
56
57
 
57
58
  # Redis: INCRBY
58
59
  define_method("incr_#{name}_by") do |increment|
59
- value = Norton.redis.with do |conn|
60
+ value = redis.with do |conn|
60
61
  conn.incrby(norton_value_key(name), increment)
61
62
  end
62
63
  instance_variable_set("@#{name}", value.to_i)
@@ -64,7 +65,7 @@ module Norton
64
65
 
65
66
  # Redis: DECRBY
66
67
  define_method("decr_#{name}_by") do |decrement|
67
- value = Norton.redis.with do |conn|
68
+ value = redis.with do |conn|
68
69
  conn.decrby(norton_value_key(name), decrement)
69
70
  end
70
71
  instance_variable_set("@#{name}", value.to_i)
@@ -74,7 +75,7 @@ module Norton
74
75
  define_method("reset_#{name}") do
75
76
  value = instance_eval(&blk)
76
77
 
77
- Norton.redis.with do |conn|
78
+ redis.with do |conn|
78
79
  conn.set(norton_value_key(name), value)
79
80
  end
80
81
  instance_variable_set("@#{name}", value)
@@ -82,7 +83,7 @@ module Norton
82
83
 
83
84
  # Redis: DEL
84
85
  define_method("remove_#{name}") do
85
- Norton.redis.with do |conn|
86
+ redis.with do |conn|
86
87
  conn.del(norton_value_key(name))
87
88
  end
88
89
  remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
@@ -7,13 +7,13 @@ module Norton
7
7
  end
8
8
 
9
9
  module ClassMethods
10
- def hash_map(name)
11
- self.register_norton_value(name, :hash_map)
10
+ def hash_map(name, options = {})
11
+ register_norton_value(name, :hash_map, options)
12
12
 
13
13
  define_method(name) do
14
14
  instance_variable_get("@#{name}") ||
15
15
  instance_variable_set("@#{name}",
16
- Norton::Objects::Hash.new(self.norton_value_key(name))
16
+ Norton::Objects::Hash.new(norton_value_key(name), :pool_name => options[:redis])
17
17
  )
18
18
  end
19
19
 
@@ -44,6 +44,18 @@ module Norton
44
44
  def norton_value_type(name)
45
45
  norton_values.dig(name.to_sym, :type)
46
46
  end
47
+
48
+ #
49
+ # 返回当前类定义的某个 Norton Value 的 redis instance
50
+ #
51
+ # @param [String] name
52
+ #
53
+ # @return [ConnectionPool]
54
+ #
55
+ def norton_value_redis_pool(name)
56
+ pool_name = norton_values.dig(name.to_sym, :redis) || :default
57
+ Norton.pools[pool_name]
58
+ end
47
59
  end
48
60
 
49
61
  #
@@ -96,11 +108,19 @@ module Norton
96
108
  # @return [Model] 当前对象
97
109
  #
98
110
  def norton_mget(*names)
99
- values = Norton.redis.with do |conn|
100
- conn.mget(names.map { |name| norton_value_key(name) })
111
+ pools_with_name = names.each_with_object({}) do |name, hash|
112
+ pool = self.class.norton_value_redis_pool(name)
113
+ hash[pool] ||= []
114
+ hash[pool] << name
101
115
  end
102
116
 
103
- assign_values(names.zip(values).to_h)
117
+ pools_with_name.each do |pool, fields|
118
+ values = pool.with do |conn|
119
+ conn.mget(fields.map { |field| norton_value_key(field) })
120
+ end
121
+
122
+ assign_values(fields.zip(values).to_h)
123
+ end
104
124
 
105
125
  self
106
126
  end
@@ -109,20 +129,23 @@ module Norton
109
129
  def assign_values(new_values)
110
130
  new_values.each do |field, val|
111
131
  type = self.class.norton_value_type(field)
132
+ ivar_name = :"@#{field}"
112
133
 
113
134
  case type
114
135
  when :counter
115
136
  value = cast_value(type, val || try("#{field}_default_value"))
116
- instance_variable_set("@#{field}", value)
137
+ instance_variable_set(ivar_name, value)
117
138
  when :timestamp
118
139
  if !val.nil?
119
- instance_variable_set("@#{field}", cast_value(type, val))
140
+ instance_variable_set(ivar_name, cast_value(type, val))
120
141
  elsif self.class.norton_values[field][:allow_nil]
121
- instance_variable_set("@#{field}", nil)
142
+ instance_variable_set(ivar_name, nil)
122
143
  else
123
144
  value = cast_value(type, try("#{field}_default_value"))
124
- instance_variable_set("@#{field}", value)
125
- Norton.redis.with { |conn| conn.set(norton_value_key(field), value) }
145
+ instance_variable_set(ivar_name, value)
146
+ self.class.norton_value_redis_pool(field).with do |conn|
147
+ conn.set(norton_value_key(field), value)
148
+ end
126
149
  end
127
150
  end
128
151
  end
@@ -1,40 +1,41 @@
1
1
  module Norton
2
2
  module Objects
3
3
  class Hash
4
- attr_reader :key
4
+ attr_reader :key, :redis
5
5
 
6
- def initialize(key)
7
- @key = key
6
+ def initialize(key, options = {})
7
+ @key = key
8
+ @redis = Norton.pools[options[:pool_name] || :default]
8
9
  end
9
10
 
10
11
  # Redis: HSET
11
12
  def hset(field, value)
12
- Norton.redis.with { |conn| conn.hset(key, field, value) }
13
+ redis.with { |conn| conn.hset(key, field, value) }
13
14
  end
14
15
  alias_method :[]=, :hset
15
16
 
16
17
  # Redis: HGET
17
18
  def hget(field)
18
- Norton.redis.with { |conn| conn.hget(key, field) }
19
+ redis.with { |conn| conn.hget(key, field) }
19
20
  end
20
21
  alias_method :get, :hget
21
22
  alias_method :[], :hget
22
23
 
23
24
  # Redis: HMGET
24
25
  def hmget(*field)
25
- Norton.redis.with { |conn| conn.hmget(key, field) }
26
+ redis.with { |conn| conn.hmget(key, field) }
26
27
  end
27
28
  alias_method :mget, :hmget
28
29
 
29
30
  # Redis: HDEL
30
31
  def hdel(*field)
31
- Norton.redis.with { |conn| conn.hdel(key, field) }
32
+ redis.with { |conn| conn.hdel(key, field) }
32
33
  end
33
34
  alias_method :delete, :hdel
34
35
 
35
36
  # Redis: HINCRBY
36
37
  def hincrby(field, by = 1)
37
- Norton.redis.with { |conn| conn.hincrby(key, field, by) }
38
+ redis.with { |conn| conn.hincrby(key, field, by) }
38
39
  end
39
40
  alias_method :incr, :hincrby
40
41
 
@@ -46,7 +47,7 @@ module Norton
46
47
 
47
48
  # Redis: HEXISTS
48
49
  def hexists(field)
49
- Norton.redis.with { |conn| conn.hexists(key, field) }
50
+ redis.with { |conn| conn.hexists(key, field) }
50
51
  end
51
52
  alias_method :include?, :hexists
52
53
  alias_method :has_key?, :hexists
@@ -55,13 +56,13 @@ module Norton
55
56
 
56
57
  # Redis: HEXISTS
57
58
  def hkeys
58
- Norton.redis.with { |conn| conn.hkeys(key) }
59
+ redis.with { |conn| conn.hkeys(key) }
59
60
  end
60
61
  alias_method :keys, :hkeys
61
62
 
62
63
  # Redis: DEL
63
64
  def clear
64
- Norton.redis.with { |conn| conn.del(key) }
65
+ redis.with { |conn| conn.del(key) }
65
66
  end
66
67
  end
67
68
  end
@@ -15,12 +15,13 @@ module Norton
15
15
  # @return [type] [description]
16
16
  def timestamp(name, options={})
17
17
  register_norton_value(name, :timestamp, options)
18
+ redis = norton_value_redis_pool(name)
18
19
 
19
20
  # Redis: GET
20
21
  define_method(name) do
21
22
  return instance_variable_get("@#{name}") if instance_variable_defined?("@#{name}")
22
23
 
23
- value = Norton.redis.with do |conn|
24
+ value = redis.with do |conn|
24
25
  raw_value = conn.get(norton_value_key(name))
25
26
  break raw_value if raw_value.present?
26
27
 
@@ -46,7 +47,7 @@ module Norton
46
47
  define_method("touch_#{name}") do
47
48
  value = options[:digits] == 13 ? (Time.current.to_f * 1000).to_i : Time.current.to_i
48
49
 
49
- Norton.redis.with do |conn|
50
+ redis.with do |conn|
50
51
  conn.set(norton_value_key(name), value)
51
52
  end
52
53
  instance_variable_set("@#{name}", value)
@@ -54,7 +55,7 @@ module Norton
54
55
 
55
56
  # Redis: DEL
56
57
  define_method("remove_#{name}") do
57
- Norton.redis.with do |conn|
58
+ redis.with do |conn|
58
59
  conn.del(norton_value_key(name))
59
60
  end
60
61
  remove_instance_variable("@#{name}") if instance_variable_defined?("@#{name}")
@@ -1,3 +1,3 @@
1
1
  module Norton
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = "~> 2.3.0"
21
+ spec.required_ruby_version = ">= 2.3.0"
22
22
 
23
23
  spec.add_dependency "redis", ">= 3.2.0"
24
24
  spec.add_dependency "connection_pool", "~> 2.2.0"
@@ -7,6 +7,10 @@ class Dummy
7
7
  candies
8
8
  end
9
9
 
10
+ counter :views_count, :redis => :tmp do
11
+ 14
12
+ end
13
+
10
14
  def id
11
15
  @id ||= Random.rand(10000)
12
16
  end
@@ -140,4 +144,19 @@ describe Norton::Counter do
140
144
  expect(dummy.instance_variable_defined?(:@candies_count)).to be(false)
141
145
  end
142
146
  end
147
+
148
+ describe "with another redis instance" do
149
+ it "saves the value in correct redis server" do
150
+ dummy.views_count = 10
151
+
152
+ value = Norton.pools[:tmp].with { |conn| conn.get(dummy.norton_value_key(:views_count)) }.to_i
153
+ expect(value).to eq(10)
154
+ end
155
+
156
+ it "gets the value correctly" do
157
+ Norton.pools[:tmp].with { |conn| conn.set(dummy.norton_value_key(:views_count), 10) }.to_i
158
+
159
+ expect(dummy.views_count).to eq(10)
160
+ end
161
+ end
143
162
  end
@@ -6,6 +6,7 @@ class Dummy
6
6
  include Norton::HashMap
7
7
 
8
8
  counter :counter1
9
+ counter :custom_redis_counter, :redis => :tmp
9
10
  timestamp :time1
10
11
  timestamp :time2, :allow_nil => true
11
12
  hash_map :map1
@@ -171,5 +172,20 @@ describe Norton::Helper do
171
172
  end
172
173
  end
173
174
  end
175
+
176
+ context "when the attributes in multiples redis servers" do
177
+ it "returns the value correctly" do
178
+ Dummy.norton_value_redis_pool(:counter1).with do |conn|
179
+ conn.set(dummy.norton_value_key(:counter1), 2)
180
+ end
181
+ Dummy.norton_value_redis_pool(:custom_redis_counter).with do |conn|
182
+ conn.set(dummy.norton_value_key(:custom_redis_counter), 99)
183
+ end
184
+
185
+ dummy.norton_mget(:counter1, :custom_redis_counter)
186
+ expect(dummy.instance_variable_get(:@counter1)).to eq(2)
187
+ expect(dummy.instance_variable_get(:@custom_redis_counter)).to eq(99)
188
+ end
189
+ end
174
190
  end
175
191
  end
@@ -2,9 +2,20 @@ require 'spec_helper'
2
2
 
3
3
  describe Norton do
4
4
  describe "#setup" do
5
- it "should setup a redis connection pool" do
6
- Norton.setup url: 'redis://localhost:6379/0'
7
- expect(Norton.redis).not_to be_nil
5
+ xit "sets a redis connection pool" do
6
+ Norton.setup(
7
+ default: { url: "redis://localhost:6379/0" }
8
+ )
9
+ expect(Norton.pools[:default]).not_to be_nil
10
+ end
11
+
12
+ xit "sets multiple redis connection pools" do
13
+ Norton.setup(
14
+ default: { url: "redis://localhost:6379/0" },
15
+ norton2: { url: "redis://localhost:6379/3" }
16
+ )
17
+ expect(Norton.pools.keys).to match_array(%i[default norton2])
18
+ expect(Norton.pools[:norton2]).not_to be_nil
8
19
  end
9
20
  end
10
21
 
@@ -15,6 +26,7 @@ describe Norton do
15
26
  include Norton::HashMap
16
27
 
17
28
  counter :counter1
29
+ counter :custom_redis_counter, :redis => :tmp
18
30
  timestamp :time1
19
31
  timestamp :time2, :allow_nil => true
20
32
  hash_map :map1
@@ -102,5 +114,20 @@ describe Norton do
102
114
  end
103
115
  end
104
116
  end
117
+
118
+ context "when the attributes in multiples redis servers" do
119
+ it "returns the value correctly" do
120
+ Dummy.norton_value_redis_pool(:counter1).with do |conn|
121
+ conn.set(dummy.norton_value_key(:counter1), 2)
122
+ end
123
+ Dummy.norton_value_redis_pool(:custom_redis_counter).with do |conn|
124
+ conn.set(dummy.norton_value_key(:custom_redis_counter), 99)
125
+ end
126
+
127
+ Norton.mget([dummy], %i[counter1 custom_redis_counter])
128
+ expect(dummy.instance_variable_get(:@counter1)).to eq(2)
129
+ expect(dummy.instance_variable_get(:@custom_redis_counter)).to eq(99)
130
+ end
131
+ end
105
132
  end
106
133
  end
@@ -21,10 +21,15 @@ RSpec.configure do |config|
21
21
 
22
22
  # Clean Up Redis
23
23
  config.before(:each) do
24
- Norton.redis.with { |conn| conn.flushdb }
24
+ Norton.pools.each do |_name, conn|
25
+ conn.with { |conn| conn.flushdb }
26
+ end
25
27
  end
26
28
  end
27
29
 
28
- Norton.setup url: "redis://localhost:6379/0"
30
+ Norton.setup(
31
+ default: { url: "redis://localhost:6379/0" },
32
+ tmp: { url: "redis://localhost:6379/2" }
33
+ )
29
34
 
30
35
  ActiveRecord::Base.establish_connection :adapter => :nulldb
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: norton
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Larry Zhao
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-07 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -213,7 +213,6 @@ files:
213
213
  - lib/norton/hash_map.rb
214
214
  - lib/norton/helper.rb
215
215
  - lib/norton/objects/hash.rb
216
- - lib/norton/timed_value.rb
217
216
  - lib/norton/timestamp.rb
218
217
  - lib/norton/version.rb
219
218
  - norton.gemspec
@@ -234,7 +233,7 @@ require_paths:
234
233
  - lib
235
234
  required_ruby_version: !ruby/object:Gem::Requirement
236
235
  requirements:
237
- - - "~>"
236
+ - - ">="
238
237
  - !ruby/object:Gem::Version
239
238
  version: 2.3.0
240
239
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -244,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
244
243
  version: '0'
245
244
  requirements: []
246
245
  rubyforge_project:
247
- rubygems_version: 2.6.12
246
+ rubygems_version: 2.6.13
248
247
  signing_key:
249
248
  specification_version: 4
250
249
  summary: Provide simple helpers on persist values in redis for performance. Works
@@ -1,40 +0,0 @@
1
- module Norton
2
- module TimedValue
3
- extend ActiveSupport::Concern
4
-
5
- module ClassMethods
6
-
7
- def timed_value(name, options={}, &blk)
8
- if options[:ttl].nil?
9
- raise 'Time to live not specified.'
10
- end
11
-
12
- if blk.nil?
13
- raise 'Value generation not provided'
14
- end
15
-
16
- # Define getter
17
- define_method(name) do
18
- Norton.redis.with do |conn|
19
- v = conn.get(self.norton_value_key(name))
20
-
21
- if v.nil?
22
- v = instance_eval(&blk)
23
- conn.setex(self.norton_value_key(name), options[:ttl], v)
24
- end
25
-
26
- v
27
- end
28
- end
29
-
30
- define_method("reset_#{name}") do
31
- Norton.redis.with do |conn|
32
- v = instance_eval(&blk)
33
- conn.setex(self.norton_value_key(name), options[:ttl], v)
34
- v
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end