feat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 58230bc0c90200195451481a106719729fe7497de3114b8853fa0458f50485de
4
+ data.tar.gz: df3875c1746cbb11955293076c588b12e11617f1f7408be51998220f17fb2fb5
5
+ SHA512:
6
+ metadata.gz: aab9efa3bd032e343be92db9fa6c19664b40528788e5f9ebde1e40085f431dee5238efe845e643ac51fc225a093d7e0b916c2f0810dc21b8e84cf3d15dbdcf48
7
+ data.tar.gz: bbbc392ec317f53960601e74ecf1421854dd75e32e360f960d611a5f82cdda262dfc7e9aad50b0d80eb5ed909cb9abc8ab1abb3ed8cab34a79b6f529cb02df89
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Hari Gopal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # Feat
2
+
3
+ TODO: Describe the gem.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'foodie'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install foodie
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here.
24
+
25
+ ## Development
26
+
27
+ TODO: Add instructions.
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/harigopal/feat.
32
+
33
+ ## License
34
+
35
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,32 @@
1
+ require 'redis'
2
+ require 'connection_pool'
3
+
4
+ require_relative 'feat/configuration'
5
+ require_relative 'feat/cache'
6
+ require_relative 'feat/uploader'
7
+
8
+ module Feat
9
+ class << self
10
+ attr_accessor :configuration
11
+
12
+ def configure
13
+ self.configuration ||= Feat::Configuration.new
14
+ yield configuration
15
+ end
16
+
17
+ def perform(feat, **opts)
18
+ audience = opts[:for]
19
+ Feat::Cache.new(feat, audience).cache_to_redis
20
+ end
21
+
22
+ def record
23
+ Feat::Uploader.new.upload_to_server
24
+ end
25
+
26
+ def redis
27
+ @redis ||= ConnectionPool.new(configuration.connection_pool) do
28
+ Redis.new(configuration.redis)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ module Feat
2
+ class Cache
3
+ def initialize(feat, audience)
4
+ @feat = feat
5
+ @audience = audience
6
+ end
7
+
8
+ def cache_to_redis
9
+ Feat.redis.with do |conn|
10
+ conn.sadd('feat:cached_dates', date)
11
+ conn.hincrby("feat:feats_on_date:#{date}", @feat, 1)
12
+ conn.sadd("feat:audience:#{namespaced_feat}", @audience) if @audience
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def date
19
+ @date ||= Time.now.utc.strftime('%Y%m%d')
20
+ end
21
+
22
+ def namespaced_feat
23
+ @namespaced_feat ||= "#{date}:#{@feat}"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ module Feat
2
+ class Configuration
3
+ attr_accessor :redis
4
+ attr_accessor :server
5
+ attr_accessor :connection_pool
6
+ attr_accessor :app_id
7
+
8
+ def initialize
9
+ @redis = {}
10
+ @server = { url: 'https://www.feathq.com/api/record' }
11
+ @connection_pool = { size: 2, timeout: 2 }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Feat
2
+ class Uploader
3
+ def upload_to_server
4
+ feats = load_feats_from_redis
5
+ send_feats_to_server(feats)
6
+ end
7
+
8
+ private
9
+
10
+ def load_feats_from_redis
11
+ Feat.redis.with do |conn|
12
+ conn.smembers('feat:cached_dates').each_with_object({}) do |cached_date, dates|
13
+ feats_on_date = conn.hgetall("feat:feats_on_date:#{cached_date}")
14
+
15
+ dates[cached_date] = feats_on_date.each_with_object({}) do |(feat, performances), feats|
16
+ audience = conn.smembers("feat:audience:#{cached_date}:#{feat}")
17
+
18
+ feats[feat] = {
19
+ performances: performances.to_i,
20
+ audience: audience
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def send_feats_to_server(feats)
28
+ uri = URI(Feat.configuration.server[:url])
29
+ app_id = Feat.configuration.app_id
30
+ Net::HTTP.post(uri, feats.to_json, 'Content-Type' => 'application/json', 'App-Id' => app_id)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Feat
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Hari Gopal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: connection_pool
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.5'
69
+ description: Unused features have a complexity cost. Feat allows you to easily record
70
+ and explore feature use in a Rails application.
71
+ email: mail@harigopal.in
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - LICENSE
77
+ - README.md
78
+ - lib/feat.rb
79
+ - lib/feat/cache.rb
80
+ - lib/feat/configuration.rb
81
+ - lib/feat/uploader.rb
82
+ - lib/feat/version.rb
83
+ homepage: https://www.github.com/harigopal/feat
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubygems_version: 3.0.2
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Track feature use in your Rails application with feat
106
+ test_files: []