simple-feed 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/rubocop.yml +33 -0
- data/.github/workflows/ruby.yml +35 -0
- data/.relaxed-rubocop-2.4.yml +174 -0
- data/.rspec +1 -1
- data/.rubocop.yml +42 -1149
- data/.rubocop_todo.yml +134 -0
- data/.travis.yml +15 -8
- data/Gemfile +2 -0
- data/Guardfile +3 -3
- data/{README.md → README.adoc} +205 -140
- data/Rakefile +6 -7
- data/bin/console +1 -0
- data/examples/shared/provider_example.rb +10 -3
- data/lib/simple-feed.rb +2 -0
- data/lib/simple_feed.rb +2 -0
- data/lib/simplefeed.rb +9 -7
- data/lib/simplefeed/activity/base.rb +2 -0
- data/lib/simplefeed/activity/multi_user.rb +8 -6
- data/lib/simplefeed/activity/single_user.rb +5 -4
- data/lib/simplefeed/dsl.rb +3 -1
- data/lib/simplefeed/dsl/activities.rb +4 -3
- data/lib/simplefeed/dsl/formatter.rb +12 -12
- data/lib/simplefeed/event.rb +4 -3
- data/lib/simplefeed/feed.rb +19 -22
- data/lib/simplefeed/key/template.rb +5 -9
- data/lib/simplefeed/key/type.rb +4 -2
- data/lib/simplefeed/providers.rb +24 -9
- data/lib/simplefeed/providers/base/provider.rb +6 -3
- data/lib/simplefeed/providers/hash.rb +2 -0
- data/lib/simplefeed/providers/hash/paginator.rb +4 -2
- data/lib/simplefeed/providers/hash/provider.rb +11 -21
- data/lib/simplefeed/providers/key.rb +20 -11
- data/lib/simplefeed/providers/proxy.rb +13 -12
- data/lib/simplefeed/providers/redis.rb +2 -0
- data/lib/simplefeed/providers/redis/driver.rb +23 -23
- data/lib/simplefeed/providers/redis/provider.rb +35 -33
- data/lib/simplefeed/providers/redis/stats.rb +12 -13
- data/lib/simplefeed/response.rb +4 -2
- data/lib/simplefeed/version.rb +3 -1
- data/simple-feed.gemspec +16 -14
- metadata +58 -41
data/Rakefile
CHANGED
@@ -1,30 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
3
5
|
|
4
6
|
require 'yard'
|
5
7
|
|
6
|
-
|
7
8
|
def shell(*args)
|
8
9
|
puts "running: #{args.join(' ')}"
|
9
10
|
system(args.join(' '))
|
10
11
|
end
|
11
12
|
|
12
13
|
task :permissions do
|
13
|
-
shell('rm -rf pkg/')
|
14
|
+
shell('rm -rf pkg/ tmp/ coverage/')
|
14
15
|
shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
|
15
16
|
shell("find . -type d -exec chmod o+x,g+x {} \\;")
|
16
17
|
end
|
17
18
|
|
18
|
-
task :
|
19
|
-
|
19
|
+
task build: :permissions
|
20
20
|
|
21
21
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
22
22
|
t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE.txt)
|
23
23
|
t.options.unshift('--title', '"SimpleFeed — Fast and Scalable "write-time" Simple Feed for Social Networks, with a Redis-based default backend implementation."')
|
24
|
-
t.after = ->
|
24
|
+
t.after = -> { exec('open doc/index.html') } if RUBY_PLATFORM =~ /darwin/
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
27
|
RSpec::Core::RakeTask.new(:spec)
|
29
28
|
|
30
|
-
task :
|
29
|
+
task default: :spec
|
data/bin/console
CHANGED
@@ -5,9 +5,17 @@ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
|
|
5
5
|
raise ArgumentError, 'No @feed defined in the enclosing example' unless defined?(@feed)
|
6
6
|
|
7
7
|
require 'simplefeed'
|
8
|
+
require 'uuid'
|
9
|
+
|
10
|
+
srand(Time.now.to_i % 100003)
|
11
|
+
|
12
|
+
@number_of_users = ARGV[0] ? ARGV[0].to_i : 2
|
13
|
+
@users = @number_of_users.times.map do |n|
|
14
|
+
n % 2 == 0 ? UUID.generate : rand(100003)
|
15
|
+
end
|
16
|
+
|
17
|
+
pp @users
|
8
18
|
|
9
|
-
@number_of_users = ARGV[0] ? ARGV[0].to_i : 1
|
10
|
-
@users = Array.new(@number_of_users) { rand(200_000_000...800_000_000) }
|
11
19
|
@activity = @feed.activity(@users)
|
12
20
|
@uid = @users.first
|
13
21
|
|
@@ -24,7 +32,6 @@ def p(*args)
|
|
24
32
|
end
|
25
33
|
|
26
34
|
with_activity(@activity) do
|
27
|
-
|
28
35
|
header "#{@activity.feed.provider_type} provider example"
|
29
36
|
|
30
37
|
wipe
|
data/lib/simple-feed.rb
CHANGED
data/lib/simple_feed.rb
CHANGED
data/lib/simplefeed.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'hashie/extensions/symbolize_keys'
|
2
4
|
require 'simplefeed/version'
|
5
|
+
require 'hashie'
|
3
6
|
|
4
7
|
Hashie.logger = Logger.new(nil)
|
5
8
|
|
@@ -17,9 +20,7 @@ module SimpleFeed
|
|
17
20
|
|
18
21
|
class << self
|
19
22
|
# @return [Hash<Symbol, Feed>] the registry of the defined feeds
|
20
|
-
|
21
|
-
@registry
|
22
|
-
end
|
23
|
+
attr_reader :registry
|
23
24
|
|
24
25
|
# @param name [Symbol] feed name
|
25
26
|
# @param options [Hash] any key-value pairs to set on the feed
|
@@ -27,9 +28,9 @@ module SimpleFeed
|
|
27
28
|
# @return [Feed] the feed with the given name, and defined via options and a block
|
28
29
|
def define(name, **options, &block)
|
29
30
|
name = name.to_sym unless name.is_a?(Symbol)
|
30
|
-
feed = registry[name]
|
31
|
+
feed = registry[name] || SimpleFeed::Feed.new(name)
|
31
32
|
feed.configure(options) do
|
32
|
-
block
|
33
|
+
block&.call(feed)
|
33
34
|
end
|
34
35
|
registry[name] = feed
|
35
36
|
feed
|
@@ -50,11 +51,12 @@ module SimpleFeed
|
|
50
51
|
def provider(provider_name, *args, **opts, &block)
|
51
52
|
provider_class = SimpleFeed::Providers.registry[provider_name]
|
52
53
|
raise ArgumentError, "No provider named #{provider_name} was found, #{SimpleFeed::Providers.registry.inspect}" unless provider_class
|
54
|
+
|
53
55
|
provider_class.new(*args, **opts, &block)
|
54
56
|
end
|
55
57
|
|
56
58
|
# Forward all other method calls to the Provider
|
57
|
-
def method_missing(name, *args, &block)
|
59
|
+
def method_missing(name, *args, **opts, &block)
|
58
60
|
registry[name] || super
|
59
61
|
end
|
60
62
|
end
|
@@ -62,7 +64,7 @@ module SimpleFeed
|
|
62
64
|
# Returns list of class attributes based on the setter methods.
|
63
65
|
# Not fool-proof, but works in this context.
|
64
66
|
def self.class_attributes(klass)
|
65
|
-
klass.instance_methods.grep(
|
67
|
+
klass.instance_methods.grep(/[^=!]=$/).map { |m| m.to_s.gsub(/=/, '').to_sym }
|
66
68
|
end
|
67
69
|
|
68
70
|
# Shortcut method to symbolize hash keys, using Hashie::Extensions
|
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
4
|
require_relative 'base'
|
3
5
|
|
4
6
|
module SimpleFeed
|
5
7
|
module Activity
|
6
8
|
class MultiUser < Base
|
7
|
-
|
8
9
|
attr_reader :user_ids
|
9
10
|
|
10
11
|
extend Forwardable
|
@@ -16,7 +17,7 @@ module SimpleFeed
|
|
16
17
|
# API Examples
|
17
18
|
# ============
|
18
19
|
#
|
19
|
-
|
20
|
+
# ```ruby
|
20
21
|
# @multi = SimpleFeed.get(:feed_name).activity(User.active.map(&:id))
|
21
22
|
#
|
22
23
|
# @multi.store(value:, at:)
|
@@ -54,15 +55,15 @@ module SimpleFeed
|
|
54
55
|
# # => [Response] { user_id => [Time] last_read, ... }
|
55
56
|
#
|
56
57
|
# @multi.total_count
|
57
|
-
# # => [Response] { user_id => [Integer] total_count, ... }
|
58
|
+
# # => [Response] { user_id => [Integer, String] total_count, ... }
|
58
59
|
#
|
59
60
|
# @multi.unread_count
|
60
|
-
# # => [Response] { user_id => [Integer] unread_count, ... }
|
61
|
+
# # => [Response] { user_id => [Integer, String] unread_count, ... }
|
61
62
|
#
|
62
63
|
# @multi.last_read
|
63
64
|
# # => [Response] { user_id => [Time] last_read, ... }
|
64
65
|
#
|
65
|
-
|
66
|
+
# ```
|
66
67
|
|
67
68
|
SimpleFeed::Providers.define_provider_methods(self) do |instance, method, *args, **opts, &block|
|
68
69
|
opts.merge!(user_ids: instance.user_ids)
|
@@ -71,8 +72,9 @@ module SimpleFeed
|
|
71
72
|
opts.delete(:event)
|
72
73
|
end
|
73
74
|
response = instance.feed.send(method, *args, **opts, &block)
|
74
|
-
|
75
|
+
block&.call(response)
|
75
76
|
raise StandardError, "Nil response from provider #{instance.feed.provider&.provider&.class}, method #{method}(#{opts})" unless response
|
77
|
+
|
76
78
|
response
|
77
79
|
end
|
78
80
|
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'base'
|
2
4
|
|
3
5
|
module SimpleFeed
|
4
6
|
module Activity
|
5
|
-
|
6
7
|
# Lazy implementation of SingleUser based on delegating an array of
|
7
8
|
# one user_id to +MultiUser+
|
8
9
|
|
@@ -16,7 +17,7 @@ module SimpleFeed
|
|
16
17
|
yield(user_id)
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
+
# ```ruby
|
20
21
|
# @activity = SimpleFeed.get(:feed_name).activity(current_user.id)
|
21
22
|
#
|
22
23
|
# @activity.store(value:, at:)
|
@@ -61,14 +62,14 @@ module SimpleFeed
|
|
61
62
|
# @activity.last_read
|
62
63
|
# # => [Time] last_read
|
63
64
|
|
64
|
-
|
65
65
|
SimpleFeed::Providers.define_provider_methods(self) do |instance, method, *args, **opts, &block|
|
66
66
|
response = instance.user_activity.send(method, *args, **opts, &block)
|
67
67
|
unless response.has_user?(instance.user_id)
|
68
68
|
raise StandardError, "Nil response from provider #{instance.feed.provider&.provider&.class}, method #{method}(#{opts}) — user_id #{instance.user_id}"
|
69
69
|
end
|
70
|
+
|
70
71
|
response = response[instance.user_id]
|
71
|
-
|
72
|
+
block&.call(response)
|
72
73
|
response
|
73
74
|
end
|
74
75
|
|
data/lib/simplefeed/dsl.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'formatter'
|
2
4
|
module SimpleFeed
|
3
5
|
module DSL
|
4
6
|
class Activities
|
5
|
-
|
6
7
|
include SimpleFeed::DSL::Formatter
|
7
8
|
|
8
9
|
attr_accessor :activity, :feed
|
@@ -14,7 +15,7 @@ module SimpleFeed
|
|
14
15
|
self.class.instance_eval do
|
15
16
|
attr_accessor key
|
16
17
|
end
|
17
|
-
|
18
|
+
send("#{key}=".to_sym, value)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -60,7 +61,7 @@ module SimpleFeed
|
|
60
61
|
|
61
62
|
def print_debug_info(method, **opts)
|
62
63
|
brackets = opts.empty? ? ['', ''] : %w{( )}
|
63
|
-
printf "\n#{
|
64
|
+
printf "\n#{feed.name.to_s.blue}.#{method.to_s.cyan.bold}#{brackets[0]}#{opts.to_s.gsub(/[{}]/, '').blue}#{brackets[1]} \n" if SimpleFeed::DSL.debug?
|
64
65
|
response = yield if block_given?
|
65
66
|
puts response.inspect.yellow if SimpleFeed::DSL.debug?
|
66
67
|
response
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'simplefeed/dsl'
|
2
4
|
require 'simplefeed/activity/single_user'
|
3
5
|
require 'simplefeed/activity/multi_user'
|
@@ -13,9 +15,9 @@ module SimpleFeed
|
|
13
15
|
|
14
16
|
def color_dump(this_activity = activity)
|
15
17
|
this_activity = if this_activity.is_a?(SimpleFeed::Activity::SingleUser)
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
this_activity.feed.activity([this_activity.user_id])
|
19
|
+
else
|
20
|
+
this_activity
|
19
21
|
end
|
20
22
|
_puts
|
21
23
|
|
@@ -32,8 +34,7 @@ module SimpleFeed
|
|
32
34
|
|
33
35
|
[['User ID', user_id, "\n"],
|
34
36
|
['Activities', sprintf('%d total, %d unread', total_count[user_id], unread_count[user_id]), "\n"],
|
35
|
-
['Last Read', this_last_read ? Time.at(this_last_read) : 'N/A'],
|
36
|
-
].each do |field, value, *args|
|
37
|
+
['Last Read', this_last_read ? Time.at(this_last_read) : 'N/A'],].each do |field, value, *args|
|
37
38
|
field(field, value, *args)
|
38
39
|
end
|
39
40
|
|
@@ -42,7 +43,6 @@ module SimpleFeed
|
|
42
43
|
this_events = fetch[user_id]
|
43
44
|
this_events_count = this_events.size
|
44
45
|
this_events.each_with_index do |_event, _index|
|
45
|
-
|
46
46
|
if this_last_event_at.nil? && _event.at < this_last_read
|
47
47
|
print_last_read_separator(this_last_read)
|
48
48
|
elsif this_last_event_at && this_last_read < this_last_event_at && this_last_read > _event.at
|
@@ -86,12 +86,12 @@ module SimpleFeed
|
|
86
86
|
|
87
87
|
def field_value(value)
|
88
88
|
case value
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
when Numeric
|
90
|
+
sprintf '%-20d', value
|
91
|
+
when Time
|
92
|
+
sprintf '%-30s', value.strftime(TIME_FORMAT)
|
93
|
+
else
|
94
|
+
sprintf '%-20s', value.to_s
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
data/lib/simplefeed/event.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module SimpleFeed
|
@@ -6,7 +8,7 @@ module SimpleFeed
|
|
6
8
|
include Comparable
|
7
9
|
|
8
10
|
def initialize(*args, value: nil, at: Time.now)
|
9
|
-
if args && args.
|
11
|
+
if args && !args.empty?
|
10
12
|
self.value = args[0]
|
11
13
|
self.at = args[1]
|
12
14
|
end
|
@@ -44,7 +46,7 @@ module SimpleFeed
|
|
44
46
|
self.value.hash
|
45
47
|
end
|
46
48
|
|
47
|
-
def to_json
|
49
|
+
def to_json(*_args)
|
48
50
|
to_h.to_json
|
49
51
|
end
|
50
52
|
|
@@ -75,6 +77,5 @@ module SimpleFeed
|
|
75
77
|
raise ArgumentError, "Required arguments missing, value=[#{value}], at=[#{at}]"
|
76
78
|
end
|
77
79
|
end
|
78
|
-
|
79
80
|
end
|
80
81
|
end
|
data/lib/simplefeed/feed.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'providers'
|
2
4
|
require_relative 'activity/base'
|
3
5
|
require 'simplefeed/key/template'
|
4
6
|
|
5
7
|
module SimpleFeed
|
6
8
|
class Feed
|
7
|
-
|
8
9
|
attr_accessor :per_page, :max_size, :batch_size, :meta, :namespace
|
9
10
|
attr_reader :name
|
10
11
|
|
@@ -18,14 +19,10 @@ module SimpleFeed
|
|
18
19
|
# set the defaults if not passed in
|
19
20
|
@meta = {}
|
20
21
|
@namespace = nil
|
21
|
-
@per_page
|
22
|
-
@max_size
|
23
|
-
@batch_size
|
24
|
-
@proxy
|
25
|
-
end
|
26
|
-
|
27
|
-
def key_template
|
28
|
-
SimpleFeed::Key::Template.new(namespace)
|
22
|
+
@per_page ||= 50
|
23
|
+
@max_size ||= 1000
|
24
|
+
@batch_size ||= 10
|
25
|
+
@proxy = nil
|
29
26
|
end
|
30
27
|
|
31
28
|
def provider=(definition)
|
@@ -38,10 +35,6 @@ module SimpleFeed
|
|
38
35
|
@proxy
|
39
36
|
end
|
40
37
|
|
41
|
-
def key(user_id)
|
42
|
-
SimpleFeed::Providers::Key.new(user_id, key_template)
|
43
|
-
end
|
44
|
-
|
45
38
|
def provider_type
|
46
39
|
SimpleFeed::Providers::Base::Provider.class_to_registry(@proxy.provider.class)
|
47
40
|
end
|
@@ -61,28 +54,32 @@ module SimpleFeed
|
|
61
54
|
user_activity(one_or_more_users)
|
62
55
|
end
|
63
56
|
|
64
|
-
# @deprecated Please use {#activity} instead
|
65
|
-
def for(*args)
|
66
|
-
STDERR.puts 'WARNING: method #for is deprecated, please use #activity'
|
67
|
-
activity(*args)
|
68
|
-
end
|
69
|
-
|
70
57
|
def configure(hash = {})
|
71
58
|
SimpleFeed.symbolize!(hash)
|
72
59
|
class_attrs.each do |attr|
|
73
|
-
|
60
|
+
send("#{attr}=", hash[attr]) if hash.key?(attr)
|
74
61
|
end
|
75
62
|
yield self if block_given?
|
76
63
|
end
|
77
64
|
|
65
|
+
def key(user_id)
|
66
|
+
SimpleFeed::Providers::Key.new(user_id, key_template)
|
67
|
+
end
|
68
|
+
|
78
69
|
def eql?(other)
|
79
70
|
other.class == self.class &&
|
80
|
-
%i(per_page max_size name).all? { |m|
|
81
|
-
|
71
|
+
%i(per_page max_size name).all? { |m| send(m).equal?(other.send(m)) } &&
|
72
|
+
provider.provider.class == other.provider.provider.class
|
82
73
|
end
|
83
74
|
|
84
75
|
def class_attrs
|
85
76
|
SimpleFeed.class_attributes(self.class)
|
86
77
|
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def key_template
|
82
|
+
SimpleFeed::Key::Template.new(namespace)
|
83
|
+
end
|
87
84
|
end
|
88
85
|
end
|
@@ -1,14 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'base62-rb'
|
2
4
|
require 'hashie/mash'
|
3
5
|
|
4
6
|
module SimpleFeed
|
5
7
|
module Key
|
6
|
-
|
7
8
|
class TextTemplate < Struct.new(:text)
|
8
9
|
def render(params = {})
|
9
|
-
output =
|
10
|
+
output = text.dup
|
10
11
|
params.each_pair do |key, value|
|
11
|
-
output.gsub!(
|
12
|
+
output.gsub!(/{{\s*#{key}\s*}}/, value.to_s)
|
12
13
|
end
|
13
14
|
output
|
14
15
|
end
|
@@ -21,8 +22,7 @@ module SimpleFeed
|
|
21
22
|
|
22
23
|
def initialize(namespace,
|
23
24
|
key_types = DEFAULT_TYPES,
|
24
|
-
text_template = DEFAULT_TEXT_TEMPLATE
|
25
|
-
)
|
25
|
+
text_template = DEFAULT_TEXT_TEMPLATE)
|
26
26
|
|
27
27
|
self.namespace = namespace
|
28
28
|
self.key_types = key_types
|
@@ -43,10 +43,6 @@ module SimpleFeed
|
|
43
43
|
def key_names
|
44
44
|
key_types.map(&:name).map(&:to_s).sort
|
45
45
|
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
46
|
end
|
50
47
|
end
|
51
48
|
end
|
52
|
-
|