norton 0.1.2 → 0.1.3

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.
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