simple-feed 2.1.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple-feed might be problematic. Click here for more details.

@@ -2,11 +2,17 @@
2
2
 
3
3
  require_relative 'providers'
4
4
  require_relative 'activity/base'
5
- require 'simplefeed/key/template'
5
+ require_relative 'providers/key'
6
6
 
7
7
  module SimpleFeed
8
8
  class Feed
9
- attr_accessor :per_page, :max_size, :batch_size, :meta, :namespace
9
+ attr_accessor :per_page,
10
+ :max_size,
11
+ :batch_size,
12
+ :namespace,
13
+ :data_key_transformer,
14
+ :meta_key_transformer
15
+
10
16
  attr_reader :name
11
17
 
12
18
  SimpleFeed::Providers.define_provider_methods(self) do |feed, method, opts, &block|
@@ -14,19 +20,21 @@ module SimpleFeed
14
20
  end
15
21
 
16
22
  def initialize(name)
17
- @name = name
18
- @name = name.underscore.to_sym unless name.is_a?(Symbol)
23
+ @name = name
24
+ @name = name.underscore.to_sym unless name.is_a?(Symbol)
19
25
  # set the defaults if not passed in
20
- @meta = {}
21
- @namespace = nil
26
+ @meta = {}
27
+ @namespace = nil
22
28
  @per_page ||= 50
23
29
  @max_size ||= 1000
24
30
  @batch_size ||= 10
31
+ @meta_key_transformer = nil
32
+ @data_key_transformer = nil
25
33
  @proxy = nil
26
34
  end
27
35
 
28
36
  def provider=(definition)
29
- @proxy = Providers::Proxy.from(definition)
37
+ @proxy = Providers::Proxy.from(definition)
30
38
  @proxy.feed = self
31
39
  @proxy
32
40
  end
@@ -63,12 +71,15 @@ module SimpleFeed
63
71
  end
64
72
 
65
73
  def key(user_id)
66
- SimpleFeed::Providers::Key.new(user_id, key_template)
74
+ SimpleFeed::Providers::Key.new(user_id,
75
+ namespace: namespace,
76
+ data_key_transformer: data_key_transformer,
77
+ meta_key_transformer: meta_key_transformer)
67
78
  end
68
79
 
69
80
  def eql?(other)
70
81
  other.class == self.class &&
71
- %i(per_page max_size name).all? { |m| send(m).equal?(other.send(m)) } &&
82
+ %i(per_page max_size name namespace data_key_transformer meta_key_transformer).all? { |m| send(m).equal?(other.send(m)) } &&
72
83
  provider.provider.class == other.provider.provider.class
73
84
  end
74
85
 
@@ -58,7 +58,7 @@ module SimpleFeed
58
58
  def with_response_batched(user_ids, external_response = nil)
59
59
  with_response(external_response) do |response|
60
60
  batch(user_ids) do |key|
61
- response.for(key.user_id) { yield(key, response) }
61
+ response.for(key.consumer) { yield(key, response) }
62
62
  end
63
63
  end
64
64
  end
@@ -46,7 +46,7 @@ module SimpleFeed
46
46
  def delete_if(user_ids:)
47
47
  with_response_batched(user_ids) do |key|
48
48
  activity(key).map do |event|
49
- if yield(event, key.user_id)
49
+ if yield(event, key.consumer)
50
50
  __delete(key, event)
51
51
  event
52
52
  end
@@ -80,7 +80,7 @@ module SimpleFeed
80
80
  def fetch(user_ids:, since: nil, reset_last_read: false)
81
81
  response = with_response_batched(user_ids) do |key|
82
82
  if since == :unread
83
- activity(key).reject { |event| event.at < user_record(key).last_read.to_f }
83
+ activity(key).reject { |event| event.at < user_meta_record(key).last_read.to_f }
84
84
  elsif since
85
85
  activity(key).reject { |event| event.at < since.to_f }
86
86
  else
@@ -94,7 +94,7 @@ module SimpleFeed
94
94
 
95
95
  def reset_last_read(user_ids:, at: Time.now)
96
96
  with_response_batched(user_ids) do |key|
97
- user_record(key)[:last_read] = at
97
+ user_meta_record(key)[:last_read] = at
98
98
  at
99
99
  end
100
100
  end
@@ -107,13 +107,13 @@ module SimpleFeed
107
107
 
108
108
  def unread_count(user_ids:)
109
109
  with_response_batched(user_ids) do |key|
110
- activity(key).count { |event| event.at > user_record(key).last_read.to_f }
110
+ activity(key).count { |event| event.at > user_meta_record(key).last_read.to_f }
111
111
  end
112
112
  end
113
113
 
114
114
  def last_read(user_ids:)
115
115
  with_response_batched(user_ids) do |key|
116
- user_record(key).last_read
116
+ user_meta_record(key).last_read
117
117
  end
118
118
  end
119
119
 
@@ -122,7 +122,7 @@ module SimpleFeed
122
122
  end
123
123
 
124
124
  def total_users
125
- h.size
125
+ h.size / 2
126
126
  end
127
127
 
128
128
  private
@@ -139,27 +139,37 @@ module SimpleFeed
139
139
  (size_before > size_after)
140
140
  end
141
141
 
142
- def create_user_record
142
+ def create_meta_record
143
143
  Hashie::Mash.new(
144
- { last_read: 0, activity: SortedSet.new }
144
+ { last_read: 0 }
145
145
  )
146
146
  end
147
147
 
148
- def user_record(key)
149
- h[key.data] ||= create_user_record
148
+ def create_data_record
149
+ Hashie::Mash.new(
150
+ { activity: SortedSet.new }
151
+ )
152
+ end
153
+
154
+ def user_data_record(key)
155
+ h[key.data] ||= create_data_record
156
+ end
157
+
158
+ def user_meta_record(key)
159
+ h[key.meta] ||= create_meta_record
150
160
  end
151
161
 
152
162
  def wipe_user_record(key)
153
- h[key.data] = create_user_record
163
+ h[key.data] = create_data_record
154
164
  end
155
165
 
156
166
  def activity(key, event = nil)
157
- user_record(key)[:activity] << event if event
158
- user_record(key)[:activity].to_a
167
+ user_data_record(key)[:activity] << event if event
168
+ user_data_record(key)[:activity].to_a
159
169
  end
160
170
 
161
171
  def add_event(event, key)
162
- uas = user_record(key)[:activity]
172
+ uas = user_data_record(key)[:activity]
163
173
  if uas.include?(event)
164
174
  false
165
175
  else
@@ -172,11 +182,11 @@ module SimpleFeed
172
182
  end
173
183
 
174
184
  def __last_read(key, _value = nil)
175
- user_record(key)[:last_read]
185
+ user_meta_record(key)[:last_read]
176
186
  end
177
187
 
178
188
  def __delete(key, event)
179
- user_record(key)[:activity].delete(event)
189
+ user_data_record(key)[:activity].delete(event)
180
190
  end
181
191
 
182
192
  def create_event(*args, **opts)
@@ -2,10 +2,6 @@
2
2
 
3
3
  require 'base62-rb'
4
4
  require 'hashie/mash'
5
- require 'simplefeed/key/template'
6
- require 'simplefeed/key/type'
7
-
8
- require 'forwardable'
9
5
 
10
6
  module SimpleFeed
11
7
  module Providers
@@ -15,66 +11,85 @@ module SimpleFeed
15
11
  # ↓ ↓
16
12
  # "ff|u.f23098.m"
17
13
  # ↑ ↑
18
- # namespace user_id(base62)
14
+ # namespace consumer(base62)
19
15
  #
20
16
  class Key
21
- attr_accessor :user_id, :key_template
17
+ class << self
18
+ def rot13(value)
19
+ value.tr('abcdefghijklmnopqrstuvwxyz',
20
+ 'nopqrstuvwxyzabcdefghijklm')
21
+ end
22
+ end
22
23
 
23
- extend Forwardable
24
- def_delegators :@key_template, :key_names, :key_types
24
+ SERIALIZED_DATA_TEMPLATE = '{{namespace}}u.{{data_id}}.d'
25
+ SERIALIZED_META_TEMPLATE = '{{namespace}}u.{{meta_id}}.m'
25
26
 
26
- def initialize(user_id, key_template)
27
- self.user_id = user_id
28
- self.key_template = key_template
27
+ attr_reader :consumer, :namespace, :data_key_transformer, :meta_key_transformer
29
28
 
30
- define_key_methods
29
+ def initialize(consumer,
30
+ namespace: nil,
31
+ data_key_transformer: nil,
32
+ meta_key_transformer: nil)
33
+ @consumer = consumer
34
+ @namespace = namespace
35
+ @data_key_transformer = data_key_transformer
36
+ @meta_key_transformer = meta_key_transformer
31
37
  end
32
38
 
33
- # Defines #data and #meta methods.
34
- def define_key_methods
35
- key_template.key_types.each do |type|
36
- key_name = type.name
37
- next if respond_to?(key_name)
38
-
39
- self.class.send(:define_method, key_name) do
40
- instance_variable_get("@#{key_name}") ||
41
- instance_variable_set("@#{key_name}", type.render(render_options))
42
- end
43
- end
39
+ def data
40
+ @data ||= render(SERIALIZED_DATA_TEMPLATE)
44
41
  end
45
42
 
46
- def base62_user_id
47
- @base62_user_id ||= if user_id.is_a?(Numeric)
48
- ::Base62.encode(user_id)
49
- else
50
- rot13(user_id.to_s)
51
- end
43
+ def meta
44
+ @meta ||= render(SERIALIZED_META_TEMPLATE)
52
45
  end
53
46
 
54
47
  def keys
55
- key_names.map { |name| send(name) }
56
- end
57
-
58
- def render_options
59
- key_template.render_options.merge!({
60
- 'user_id' => user_id,
61
- 'base62_user_id' => base62_user_id
62
- })
48
+ [data, meta]
63
49
  end
64
50
 
65
51
  def to_s
66
- super + { user_id: user_id, base62_user_id: base62_user_id, keys: keys }.to_s
52
+ super + key_params.to_s
67
53
  end
68
54
 
69
55
  def inspect
70
- render_options.inspect
56
+ super + key_params.inspect
71
57
  end
72
58
 
73
59
  private
74
60
 
75
- def rot13(value)
76
- value.tr('abcdefghijklmnopqrstuvwxyz',
77
- 'nopqrstuvwxyzabcdefghijklm')
61
+ def render(template)
62
+ template.dup.tap do |output|
63
+ key_params.each_pair do |key, value|
64
+ output.gsub!(/{{#{key}}}/, value.to_s)
65
+ end
66
+ end
67
+ end
68
+
69
+ def obscure_value(id)
70
+ id = id.to_i if id.is_a?(String) && id =~ /^[\d]+$/
71
+
72
+ if id.is_a?(Numeric)
73
+ ::Base62.encode(id)
74
+ else
75
+ self.class.rot13(id.to_s)
76
+ end
77
+ end
78
+
79
+ def key_params
80
+ @key_params ||= Hashie::Mash.new(
81
+ namespace: namespace ? "#{namespace}|" : '',
82
+ data_id: obscure_value(data_id),
83
+ meta_id: obscure_value(meta_id)
84
+ )
85
+ end
86
+
87
+ def meta_id
88
+ meta_key_transformer&.call(consumer) || consumer
89
+ end
90
+
91
+ def data_id
92
+ data_key_transformer&.call(consumer) || consumer
78
93
  end
79
94
  end
80
95
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module SimpleFeed
4
4
  module Providers
5
+ RUBY_MAJOR_VERSION = RUBY_VERSION.split('.')[0..1].join.to_i
6
+
5
7
  class Proxy
6
8
  attr_accessor :provider
7
9
 
@@ -15,7 +17,7 @@ module SimpleFeed
15
17
  end
16
18
 
17
19
  def initialize(provider_or_klass, *args, **options)
18
- self.provider = if provider_or_klass.is_a?(::String)
20
+ self.provider = if provider_or_klass.is_a?(::String) || provider_or_klass.is_a?(::Symbol)
19
21
  ::Object.const_get(provider_or_klass).new(*args, **options)
20
22
  else
21
23
  provider_or_klass
@@ -26,12 +28,23 @@ module SimpleFeed
26
28
  end
27
29
  end
28
30
 
29
- # Forward all other method calls to Provider
30
- def method_missing(name, *args, **opts, &block)
31
- if provider&.respond_to?(name)
32
- provider.send(name, *args, **opts, &block)
33
- else
34
- super(name, *args, **opts, &block)
31
+ if RUBY_MAJOR_VERSION >= 27
32
+ # Forward all other method calls to Provider
33
+ def method_missing(name, *args, **opts, &block)
34
+ if provider&.respond_to?(name)
35
+ provider.send(name, *args, **opts, &block)
36
+ else
37
+ super(name, *args, **opts, &block)
38
+ end
39
+ end
40
+ else
41
+ # Forward all other method calls to Provider
42
+ def method_missing(name, *args, &block)
43
+ if provider&.respond_to?(name)
44
+ provider.send(name, *args, &block)
45
+ else
46
+ super(name, *args, &block)
47
+ end
35
48
  end
36
49
  end
37
50
  end
@@ -51,9 +51,9 @@ module SimpleFeed
51
51
  raise ArgumentError, '#delete_if must be called with a block that receives (user_id, event) as arguments.' unless block_given?
52
52
 
53
53
  with_response_batched(user_ids) do |key|
54
- fetch(user_ids: [key.user_id])[key.user_id].map do |event|
54
+ fetch(user_ids: [key.consumer])[key.consumer].map do |event|
55
55
  with_redis do |redis|
56
- if yield(event, key.user_id)
56
+ if yield(event, key.consumer)
57
57
  redis.zrem(key.data, event.value) ? event : nil
58
58
  end
59
59
  end
@@ -90,7 +90,7 @@ module SimpleFeed
90
90
 
91
91
  response = with_response_pipelined(user_ids) do |redis, key|
92
92
  if since == :unread
93
- redis.zrevrangebyscore(key.data, '+inf', (last_read_response.delete(key.user_id) || 0).to_f, withscores: true)
93
+ redis.zrevrangebyscore(key.data, '+inf', (last_read_response.delete(key.consumer) || 0).to_f, withscores: true)
94
94
  elsif since
95
95
  redis.zrevrangebyscore(key.data, '+inf', since.to_f, withscores: true)
96
96
  else
@@ -120,7 +120,7 @@ module SimpleFeed
120
120
  get_users_last_read(redis, key)
121
121
  end
122
122
  with_response_pipelined(response.user_ids, response) do |redis, key, _response|
123
- last_read = _response.delete(key.user_id).to_f
123
+ last_read = _response.delete(key.consumer).to_f
124
124
  redis.zcount(key.data, last_read, '+inf')
125
125
  end
126
126
  end
@@ -223,7 +223,7 @@ module SimpleFeed
223
223
  def with_response_pipelined(user_ids, response = nil)
224
224
  with_response(response) do |response|
225
225
  batch_pipelined(user_ids) do |redis, key|
226
- response.for(key.user_id) { yield(redis, key, response) }
226
+ response.for(key.consumer) { yield(redis, key, response) }
227
227
  end
228
228
  end
229
229
  end
@@ -231,7 +231,7 @@ module SimpleFeed
231
231
  def with_response_multi(user_ids, response = nil)
232
232
  with_response(response) do |response|
233
233
  batch_multi(user_ids) do |redis, key|
234
- response.for(key.user_id) { yield(redis, key, response) }
234
+ response.for(key.consumer) { yield(redis, key, response) }
235
235
  end
236
236
  end
237
237
  end
@@ -28,7 +28,7 @@ module SimpleFeed
28
28
 
29
29
  def for(key_or_user_id, result = nil)
30
30
  user_id = key_or_user_id.is_a?(SimpleFeed::Providers::Key) ?
31
- key_or_user_id.user_id :
31
+ key_or_user_id.consumer :
32
32
  key_or_user_id
33
33
 
34
34
  @result[user_id] = result || yield(@result[user_id])
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleFeed
4
- VERSION = '2.1.0'
4
+ VERSION = '3.0.1'
5
5
  end
Binary file
Binary file
@@ -2,7 +2,8 @@
2
2
 
3
3
  lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'simplefeed/version'
5
+ # noinspection RubyResolve
6
+ load File.expand_path("#{lib}/simplefeed/version.rb")
6
7
 
7
8
  Gem::Specification.new do |spec|
8
9
  spec.name = 'simple-feed'
@@ -30,10 +31,13 @@ Gem::Specification.new do |spec|
30
31
  spec.add_dependency 'hashie'
31
32
  spec.add_dependency 'hiredis'
32
33
  spec.add_dependency 'redis'
34
+ spec.add_dependency 'tty-box'
35
+ spec.add_dependency 'tty-screen'
33
36
 
34
37
  spec.add_development_dependency 'awesome_print'
35
38
  spec.add_development_dependency 'bundler'
36
39
  spec.add_development_dependency 'codeclimate-test-reporter'
40
+ spec.add_development_dependency 'codecov'
37
41
  spec.add_development_dependency 'rake'
38
42
  spec.add_development_dependency 'rspec'
39
43
  spec.add_development_dependency 'rspec-its'