simple-feed 2.0.1 → 2.0.2

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: de6f18bbf9e002e7f1ee3fa49a7675ea66320bc4
4
- data.tar.gz: 1325dfc4fed1fe485aef9d2fcd0a75442022caee
3
+ metadata.gz: c0041dae8cf2aeff75f069680843b654093dad50
4
+ data.tar.gz: 6c21de78f66d8e964eecd08296f415061f288423
5
5
  SHA512:
6
- metadata.gz: d90c16eaca736fe56ae19a4c2df0688a9267f00863f18a713ac678ec9150210e94553945636450651563af35706f4ec68dcb113fa451a7109c7376bcb5704363
7
- data.tar.gz: 758243acc5437bc4f022dfbeaa5b93d3af01525ec972760fe33cca1756de220e4b2b344c5e2f7e771578f8fdb24aef662e4abad8a9ba09ace74776c0512e37d8
6
+ metadata.gz: 3a3377a50d75428dcc155bbb3d156fd6b8e394c845c690ec23d5a2b6e083a39feded268a40a80e16e5fe9cb33ad6f68f872a51690a0c4c3f7ada8587aad3ec54
7
+ data.tar.gz: 5c436ae8b4c7cac404f40aef9c7cf614c8dd8788a998d567139bd2cca0fc10c1a815943bc80374f10db8ef8375f5f6db3ee74af6c89253570b5e9b4ed78b5baf
@@ -1,7 +1,7 @@
1
1
  cache: bundler
2
2
  rvm:
3
- - 2.3.1
4
- - 2.4.0-preview2
3
+ - 2.3.3
4
+ - 2.4.0
5
5
  services:
6
6
  - redis-server
7
7
  before_script:
data/README.md CHANGED
@@ -1,69 +1,56 @@
1
1
  # SimpleFeed — Scalable, easy to use activity feed implementation.
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/simple-feed.svg)](https://badge.fury.io/rb/simple-feed)
3
+
4
+ [![Gem Version](https://img.shields.io/gem/v/simple-feed.svg)](https://rubygems.org/gems/simple-feed)
4
5
  [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/kigster/simple-feed/master/LICENSE.txt)
6
+
5
7
  [![Build Status](https://travis-ci.org/kigster/simple-feed.svg?branch=master)](https://travis-ci.org/kigster/simple-feed)
6
8
  [![Code Climate](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/badges/8b899f6df4fc1ed93759/gpa.svg)](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/feed)
7
9
  [![Test Coverage](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/badges/8b899f6df4fc1ed93759/coverage.svg)](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/coverage)
8
10
  [![Issue Count](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/badges/8b899f6df4fc1ed93759/issue_count.svg)](https://codeclimate.com/repos/58339a5b3d9faa74ac006b36/feed)
9
11
  [![Inline docs](http://inch-ci.org/github/kigster/simple-feed.svg?branch=master)](http://inch-ci.org/github/kigster/simple-feed)
12
+ [![Talk on Gitter](https://img.shields.io/gitter/room/gitterHQ/gitter.svg)](https://gitter.im/kigster/simple-feed)
10
13
 
11
- This is a fast, pure-ruby implementation of an activity feed concept commonly used in social networking applications. The implementation is optimized for **read-time performance** and high concurrency (lots of users), and can be extended with custom backend providers. Two providers come bundled: the production-ready Redis provider, and a naive pure Hash-based provider.
12
-
13
- __Important Notes and Acknowledgements:__
14
+ ---
14
15
 
15
- * SimpleFeed *does not depend on Ruby on Rails* and is a __pure-ruby__ implementation.
16
- * __SimpleFeed requires ruby 2.3 or later.__
17
- * SimpleFeed is currently live in production.
18
- * We'd like to thank __[Simbi, Inc — Symbiotic Economy](http://simbi.com)__ for their sponsorship of the development of this open source library.
16
+ **February 20th, 2017**: Please read the blog post [Feeding Frenzy with SimpleFeed](http://kig.re/2017/02/19/feeding-frenzy-with-simple-feed-activity-feed-ruby-gem.html) launching this library. Please leave comments or questions in the discussion thread at the bottom of that post. Thanks!
19
17
 
20
- ## What is an activity feed?
18
+ ---
21
19
 
22
- > Activity feed is a visual representation of a time-ordered, reverse chronological list of events which can be:
23
- >
24
- > * personalized for a given user or a group, or global
25
- > * aggregated across several actors for a similar event type, eg. "John, Mary, etc.. followed George"
26
- > * filtered by a certain characteristic, such as:
27
- > * the actor producing an event — i.e. people you follow on a social network, or "yourself" for your own activity
28
- > * the type of an event (i.e. posts, likes, comments, stories, etc)
29
- > * the target of an event (commonly a user, but can also be a thing you are interested in, e.g. a github repo you are watching)
20
+ If you like to see this project grow, your donation of any amount is much appreciated.
30
21
 
31
- Here is an example of a real feed powered by this library, and which is very common on today's social media sites:
22
+ [![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FSFYYNEQ8RKWU)
32
23
 
33
- [![Example](https://raw.githubusercontent.com/kigster/simple-feed/master/man/activity-feed-action.png)](https://raw.githubusercontent.com/kigster/simple-feed/master/man/activity-feed-action.png)
24
+ ---
34
25
 
35
- What you publish into your feed i.e. _stories_ or _events_, will depend entirely on your application. SimpleFeed should be able to power the most demanding *write-time* feeds.
26
+ This is a fast, pure-ruby implementation of an activity feed concept commonly used in social networking applications. The implementation is optimized for **read-time performance** and high concurrency (lots of users), and can be extended with custom backend providers. Two providers come bundled: the production-ready Redis provider, and a naive Ruby Hash-based provider.
36
27
 
37
- ## Challenges
28
+ __Important Notes and Acknowledgements:__
38
29
 
39
- Building a personalized activity feed tends to be a challenging task, due to the diversity of event types that it often includes, the personalization requirement, and the need for it to often scale to very large numbers of concurrent users. Therefore common implementations tend to focus on either:
30
+ * SimpleFeed *does not depend on Ruby on Rails* and is a __pure-ruby__ implementation
31
+ * SimpleFeed requires ruby 2.3 or later
32
+ * SimpleFeed is currently live in production
33
+ * SimpleFeed is open source thanks to the generosity of __[Simbi, Inc](http://simbi.com)__.
40
34
 
41
- * optimizing the read time performance by pre-computing the feed for each user ahead of time
42
- * OR optimizing the various ranking algorithms by computing the feed at read time, with complex forms of caching addressing the performance requirements.
43
-
44
- The first type of feed is much simpler to implement on a large scale (up to a point), and it scales well if the data is stored in a light-weight in-memory storage such as Redis. This is exactly the approach this library takes.
35
+ ## Background, Examples, Serialization, etc
45
36
 
46
- For more information about various types of feed, and the typical architectures that power them — please read:
37
+ Please read the additional documentation, including the examples, on the [project's Github Wiki](https://github.com/kigster/simple-feed/wiki).
47
38
 
48
- - ["How would you go about building an activity feed like Facebook?"](https://hashnode.com/post/architecture-how-would-you-go-about-building-an-activity-feed-like-facebook-cioe6ea7q017aru53phul68t1/answer/ciol0lbaa02q52s530vfqea0t) by [Lee Byron](https://hashnode.com/@leebyron).
49
- - ["Feeding Frenzy: Selectively Materializing Users’ Event Feeds"](http://jeffterrace.com/docs/feeding-frenzy-sigmod10-web.pdf) (Yahoo! Research paper).
39
+ ## Usage
50
40
 
51
- ## Overview
41
+ A key concept to understanding SimpleFeed gem, is that of a _provider_, which is effectively a persistence implementation for the events belonging to each user.
52
42
 
53
- The feed library aims to address the following goals:
43
+ Two providers are supplied with this gem:
54
44
 
55
- * To define a minimalistic API for a typical event-based simple feed, without tying it to any concrete provider implementation
56
- * To make it easy to implement and plug in a new type of provider, eg. using *Couchbase* or *MongoDB*
57
- * To provide a scalable default provider implementation using Redis, which can support millions of users via sharding
58
- * To support multiple simple feeds within the same application, but used for different purposes, eg. simple feed of my followers, versus simple feed of my own actions.
45
+ * The production-ready `:redis` provider, which uses the [sorted set Redis data type](https://redislabs.com/ebook/redis-in-action/part-2-core-concepts-2/chapter-3-commands-in-redis/3-5-sorted-sets) to store and fetch the events, scored by time (but not necessarily).
59
46
 
60
- ## Usage
47
+ * The naïve `:hash` provider based on the ruby `Hash` class, that can be useful in unit tests, or in simple simulations.
61
48
 
62
- First you need to configure the Feed with a valid provider implementation and a name.
49
+ You initialize a provider by using the `SimpleFeed.provider([Symbol])` method.
63
50
 
64
51
  ### Configuration
65
52
 
66
- Below we configure a feed called `:newsfeed`, which presumably will be populated with the events coming from the followers.
53
+ Below we configure a feed called `:newsfeed`, which in this example will be populated with the various events coming from the followers.
67
54
 
68
55
  ```ruby
69
56
  require 'simplefeed'
@@ -110,7 +97,7 @@ application, not just the one that published the event (which is the
110
97
  case for the "toy" `Hash::Provider`.
111
98
 
112
99
  ```ruby
113
- activity.paginate(page: 1)
100
+ activity.paginate(page: 1, reset_last_read: true)
114
101
  # => [ <SimpleFeed::Event#0x2134afa value='hello' at='2016-11-20 23:32:56 -0800'> ]
115
102
  ```
116
103
 
@@ -158,8 +145,8 @@ activity.unread_count # => 0
158
145
  activity.store(value: 'hello') # => true
159
146
  activity.store(value: 'goodbye', at: Time.now - 20) # => true
160
147
  activity.unread_count # => 2
161
- # Now we can paginate the events, which by default resets "last_read" timestamp the user
162
- activity.paginate(page: 1)
148
+ # Now we can paginate the events, while resetting this user's last-read timestamp:
149
+ activity.paginate(page: 1, reset_last_read: true)
163
150
  # [
164
151
  # [0] #<SimpleFeed::Event: value=good bye, at=1480475294.0579991>,
165
152
  # [1] #<SimpleFeed::Event: value=hello, at=1480475294.057138>
@@ -179,7 +166,7 @@ end
179
166
  activity.total_count # => 0
180
167
  ```
181
168
 
182
- You can fetch all items (optionally filtered by time) in the feed using `#fetch`, and you can
169
+ You can fetch all items (optionally filtered by time) in the feed using `#fetch`,
183
170
  `#paginate` and reset the `last_read` timestamp by passing the `reset_last_read: true` as a parameter.
184
171
 
185
172
  <a name="batch-api"/>
@@ -296,7 +283,10 @@ end
296
283
  # => [Response] { user_id => [Boolean], ... } true if user activity was found and deleted, false otherwise
297
284
 
298
285
  # Return a paginated list of all items, optionally with the total count of items
299
- @multi.paginate(page:, per_page:, with_total: false, reset_last_read: false)
286
+ @multi.paginate(page: 1,
287
+ per_page: @multi.feed.per_page,
288
+ with_total: false,
289
+ reset_last_read: false)
300
290
  # => [Response] { user_id => [Array]<Event>, ... }
301
291
  # Options:
302
292
  # reset_last_read: false — reset last read to Time.now (true), or the provided timestamp
@@ -325,21 +315,26 @@ end
325
315
 
326
316
  ```
327
317
 
328
- ## Providers
318
+ ## Providers in Depth
329
319
 
330
- A provider is an underlying implementation that persists the events for each user, together with some meta-data for each feed.
320
+ As we've discussed above, a provider is an underlying persistence mechanism implementation.
331
321
 
332
322
  It is the intention of this gem that:
333
323
 
334
- * it should be easy to swap providers
335
- * it should be easy to add new providers
324
+ * it should be easy to write new providers
325
+ * it should be easy to swap out providers
336
326
 
337
- Each provider must implement exactly the public API of a provider shown
338
- above (the `Feed` version, that receives `user_ids:` as arguments).
327
+ To create a new provider please use `SimpleFeed::Providers::Hash::Provider` class as a starting point.
339
328
 
340
329
  Two providers are available with this gem:
341
330
 
342
- * `SimpleFeed::Providers::Redis::Provider` is the production-ready provider that uses the [sorted set Redis data type](https://redislabs.com/ebook/redis-in-action/part-2-core-concepts-2/chapter-3-commands-in-redis/3-5-sorted-sets) and their operations operations to store the events, scored by their time typically (but not necessarily). This provider is highly optimized for massive writes and can be sharded by using a _Twemproxy_ backend, and many small Redis shards.
331
+ ### `SimpleFeed::Providers::Redis::Provider`
332
+
333
+ Redis Provider is a production-ready persistence adapter that uses the [sorted set Redis data type](https://redislabs.com/ebook/redis-in-action/part-2-core-concepts-2/chapter-3-commands-in-redis/3-5-sorted-sets).
334
+
335
+ This provider is optimized for large writes and can use either a single Redis instance for all users of your application, or any number of Redis [shards](https://en.wikipedia.org/wiki/Shard_(database_architecture)) by using a [_Twemproxy_](https://github.com/twitter/twemproxy) in front of the Redis shards.
336
+
337
+ While future
343
338
 
344
339
  * `SimpleFeed::Providers::HashProvider` is a pure Hash-like implementation of a provider that can be useful in unit tests of a host application. This provider could be used to write and read events within a single ruby process, can be serialized to and from a YAML file, and is therefore intended primarily for Feed emulations in automated tests.
345
340
 
data/Rakefile CHANGED
@@ -4,6 +4,20 @@ require 'rspec/core/rake_task'
4
4
  require 'yard'
5
5
 
6
6
 
7
+ def shell(*args)
8
+ puts "running: #{args.join(' ')}"
9
+ system(args.join(' '))
10
+ end
11
+
12
+ task :permissions do
13
+ shell('rm -rf pkg/')
14
+ shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
15
+ shell("find . -type d -exec chmod o+x,g+x {} \\;")
16
+ end
17
+
18
+ task :build => :permissions
19
+
20
+
7
21
  YARD::Rake::YardocTask.new(:doc) do |t|
8
22
  t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE.txt)
9
23
  t.options.unshift('--title', '"SimpleFeed — Fast and Scalable "write-time" Simple Feed for Social Networks, with a Redis-based default backend implementation."')
@@ -40,8 +40,8 @@ with_activity(@activity) do
40
40
 
41
41
  header 'paginate(page: 1, per_page: 2)'
42
42
  paginate(page: 1, per_page: 2) { |r| puts r[@uid].map(&:to_color_s) }
43
- header 'paginate(page: 2, per_page: 2)'
44
- paginate(page: 2, per_page: 2) { |r| puts r[@uid].map(&:to_color_s) }
43
+ header 'paginate(page: 2, per_page: 2, reset_last_read: true)'
44
+ paginate(page: 2, per_page: 2, reset_last_read: true) { |r| puts r[@uid].map(&:to_color_s) }
45
45
 
46
46
  hr
47
47
 
@@ -1,6 +1,8 @@
1
1
  require 'hashie/extensions/symbolize_keys'
2
2
  require 'simplefeed/version'
3
3
 
4
+ Hashie.logger = Logger.new(nil)
5
+
4
6
  ::Dir.glob(::File.expand_path('../simplefeed/*.rb', __FILE__)).each { |f| require_relative(f) }
5
7
 
6
8
  require 'simplefeed/providers/redis'
@@ -20,12 +20,6 @@ module SimpleFeed
20
20
  SimpleFeed::Providers.register(class_to_registry(klass), klass)
21
21
  end
22
22
 
23
- # SimpleFeed::Providers::REQUIRED_METHODS.each do |m|
24
- # define_method(m) do |*|
25
- # raise ::SimpleFeed::Providers::NotImplementedError.new(self, m)
26
- # end
27
- # end
28
-
29
23
  protected
30
24
 
31
25
  def reset_last_read_value(user_ids:, at: nil)
@@ -121,12 +121,7 @@ SimpleFeed::Redis::Driver.new(redis: { host: 'localhost', port: 6379, db: 1, tim
121
121
  send_proc = redis_method if redis_method.respond_to?(:call)
122
122
  send_proc ||= ->(redis) { redis.send(redis_method, *args, &block) }
123
123
 
124
- if opts[:pipelined]
125
- opts.delete :pipelined
126
- with_pipelined { |redis| send_proc.call(redis) }
127
- else
128
- with_redis { |redis| send_proc.call(redis) }
129
- end
124
+ with_redis { |redis| send_proc.call(redis) }
130
125
  end
131
126
 
132
127
  class MockRedis
@@ -9,8 +9,6 @@ require 'simplefeed/providers/key'
9
9
  require_relative 'driver'
10
10
  require_relative 'stats'
11
11
 
12
- require 'pp'
13
-
14
12
  module SimpleFeed
15
13
  module Providers
16
14
  module Redis
@@ -1,3 +1,3 @@
1
1
  module SimpleFeed
2
- VERSION = '2.0.1'
2
+ VERSION = '2.0.2'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-feed
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-29 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base62-rb
@@ -314,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
314
314
  version: '0'
315
315
  requirements: []
316
316
  rubyforge_project:
317
- rubygems_version: 2.6.6
317
+ rubygems_version: 2.6.13
318
318
  signing_key:
319
319
  specification_version: 4
320
320
  summary: Create multiple types of social networking activity feeds with simple-feed