tailslide 0.1.0 → 0.1.4

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
  SHA256:
3
- metadata.gz: e1a5e8473d47cabf7b875eed87f308f7ce87146c9f985be62f03c8de6122fa04
4
- data.tar.gz: 7de6db758b0fc8fd7034212ace03061c53a7fc717ab3e68dc87bc46450f69098
3
+ metadata.gz: d317d72da4b918e8c57feaf8072884cbc8ecdcb10ab3e49eefc9a392cb7a71ce
4
+ data.tar.gz: 4edf3d36bf65775916ed49d79ff8c28bd128c91c630bde5b21091353df495d2e
5
5
  SHA512:
6
- metadata.gz: 70b5ddcb2530404fefa63309de3ffbeab55b078cfbd7578890e92e40be4d035510a4c9c3c324a02465894fd8f8e1cab55423ad638acd3911ac73b08973daaaa8
7
- data.tar.gz: 17cb8385bdb5c5f320dda627f33ff333ab6a34ae3853d66dfdc8b37bfaf64f124cf2cd2f8bd8572ab043c1fcd1c32dfc8c205e672553c1c69edeb4741bfbe68e
6
+ metadata.gz: 796bfd026bb228dd49a089a8ed87b8785bc21e7e667e2b6c4f3237a0b3e4de41f3ace73be4efb3b9161baf2c187abb66a74a7f21f8f76c906fef554b1d230659
7
+ data.tar.gz: 41884a753fed4a3e7c77773ef76059f3cdb1ccd9e63b56cd5efa5ab040590d1726cd1862153ef0eed06eb342d19e5b61868f50a6c2fc17a2c5ef6b6776fc1345
@@ -0,0 +1,14 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Debug Local File",
9
+ "type": "Ruby",
10
+ "request": "launch",
11
+ "program": "./test.rb"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "workbench.colorCustomizations": {
3
+ "sash.hoverBorder": "#3b3b3b",
4
+ "titleBar.activeBackground": "#222222",
5
+ "titleBar.activeForeground": "#e7e7e7",
6
+ "titleBar.inactiveBackground": "#22222299",
7
+ "titleBar.inactiveForeground": "#e7e7e799",
8
+ "commandCenter.border": "#e7e7e799"
9
+ },
10
+ "editor.acceptSuggestionOnEnter": "on"
11
+ }
data/Gemfile CHANGED
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in tailslide.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
8
+ gem 'async', '~> 2,0.3'
9
+ gem 'nats-pure', '~> 2,1.0'
10
+ gem 'rake', '~> 13.0'
11
+ gem 'redis', '~>4.7.1'
12
+ gem 'redistimeseries', '~>0.1.2'
9
13
 
10
- gem "minitest", "~> 5.0"
14
+ gem 'minitest', '~> 5.0'
11
15
 
12
- gem "rubocop", "~> 1.21"
16
+ gem 'rubocop', '~> 1.21'
data/README.md CHANGED
@@ -1,43 +1,215 @@
1
- # Tailslide
1
+ # Ruby SDK for Tailslide
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/tailslide`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ ---
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ This package is a server-side SDK for applications written in Ruby for the Tailslide feature flag framework.
6
+
7
+ Visit the https://github.com/tailslide-io repository or see Tailslide’s [case study](https://tailslide-io.github.io) page for more information.
6
8
 
7
9
  ## Installation
8
10
 
9
- Add this line to your application's Gemfile:
11
+ ---
12
+
13
+ Install the Tailslide npm package with `gem install tailslide`
14
+
15
+ ## Basic Usage
16
+
17
+ ---
18
+
19
+ ### Instantiating and Initializing FlagManager
20
+
21
+ The `FlagManager`class is the entry point of this SDK. It is responsible for retrieving all the flag rulesets for a given app with its `app_id` and creating new `Toggler` instances to handle toggling of feature flags within that app. To instantiate a `FlagManager` object, a user must provide a configuration object:
22
+
23
+ ```ruby
24
+ require "async"
25
+ require('tailslide')
26
+
27
+ config = {
28
+ nats_server: "nats://localhost:4222",
29
+ nats_stream: "flags_ruleset",
30
+ app_id: 1,
31
+ user_context: "375d39e6-9c3f-4f58-80bd-e5960b710295",
32
+ sdk_key: "myToken",
33
+ redis_host: "http://localhost",
34
+ redis_port: 6379,
35
+ }
36
+
37
+ Async do |task|
38
+ manager = FlagManager.new(**config)
39
+ manager.initialize_flags
40
+
41
+ end
42
+ ```
43
+
44
+ - `nats_server` is the NATS JetStream server `address:port`
45
+ - `nats_stream` is the NATS JetStream’s stream name that stores all the apps and their flag rulesets
46
+ - `app_id` is the ID number of the app the user wants to retrieve its flag ruleset from
47
+ - `user_context` is the UUID string that identifies the current user
48
+ - `sdk_key` is the SDK key for the Tailslide, it is used as a password for NATS JetStream token authentication
49
+ - `redis_host` is the address to the Redis database
50
+ - `redis_port` is the port number that the Redis database runs on
51
+
52
+ After instantiating a `FlagManager`, invoke the `initialize` method. This method connects the `FlagManager` instance to both NATS JetStream and Redis Timeseries, and asynchronously retrieves the latest and any new flag ruleset data.
53
+
54
+ ---
55
+
56
+ ### Using Feature Flag with Toggler
57
+
58
+ Once the `FlagManager` is initialized, it can create a `Toggler`, with the `new_toggler` method, for each feature flag that the developer wants to wrap the new and old features in. A `Toggler`’s `is_flag_active` method checks whether the flag with its `flag_name` is active or not based on the flag ruleset. A `Toggler`’s `is_flag_active` method returns a boolean value, which is intended to be used to control branching logic flow within an application at runtime, to invoke new features.
59
+
60
+ ```ruby
61
+ flag_config = {
62
+ flag_name: 'App 1 Flag 1',
63
+ }
64
+
65
+ flag_toggler = manager.new_toggler(flag_config)
66
+
67
+ if flag_toggler.is_flag_active
68
+ # call new feature here
69
+ else
70
+ # call old feature here
71
+ end
72
+ ```
73
+
74
+ ---
75
+
76
+ ### Emitting Success or Failture
77
+
78
+ To use the `Toggler` instances to record successful or failed operations, call its `emit_success` or `emit_failure` methods:
10
79
 
11
80
  ```ruby
12
- gem 'tailslide'
81
+ if successCondition
82
+ flag_toggler.emit_success
83
+ else
84
+ flag_toggler.emit_failure
85
+ end
13
86
  ```
14
87
 
15
- And then execute:
88
+ ## Documentation
89
+
90
+ ---
91
+
92
+ ### FlagManager
93
+
94
+ The `FlagManager` class is the entry point of the SDK. A new `FlagManager` object will need to be created for each app.
95
+
96
+ #### FlagManager Constructor
97
+
98
+ **Parameters:**
99
+
100
+ - An object with the following keys
101
+ - `server` a string that represents the URL and port of the NATS server.
102
+ - `app_id` a number representing the application the microservice belongs to
103
+ - `sdk_key` a string generated via the Tower front-end for NATS JetStream authentication
104
+ - `user_context` a string representing the user’s UUID
105
+ - `redis_host` a string that represents the url of the Redis server
106
+ - `redis_port` a number that represents the port number of the Redis server
107
+
108
+ ---
109
+
110
+ #### Instance Methods
111
+
112
+ ##### `FlagManager.prototype.set_user_context(new_user_context)`
113
+
114
+ **Parameters:**
115
+
116
+ - A UUID string that represents the current active user
117
+
118
+ **Return Value:**
119
+
120
+ - `null`
121
+
122
+ ---
123
+
124
+ ##### `FlagManager.prototype.get_user_context()`
125
+
126
+ **Parameters:**
127
+
128
+ - `null`
129
+
130
+ **Return Value:**
131
+
132
+ - The UUID string that represents the current active user
133
+
134
+ ---
135
+
136
+ ##### `FlagManager.prototype.new_toggler(options)`
137
+
138
+ Creates a new toggler to check for a feature flag's status from the current app's flag ruleset by the flag's name.
139
+
140
+ **Parameters:**
141
+
142
+ - An object with key of `flag_name` and a string value representing the name of the feature flag for the new toggler to check whether the new feature is enabled
143
+
144
+ **Return Value:**
145
+
146
+ - A `Toggler` object
147
+
148
+ ---
149
+
150
+ ##### `FlagManager.prototype.disconnect()`
151
+
152
+ Asynchronously disconnects the `FlagManager` instance from NATS JetStream and Redis database
153
+
154
+ **Parameters:**
155
+
156
+ - `null`
157
+
158
+ **Return Value:**
159
+
160
+ - `null`
161
+
162
+ ---
163
+
164
+ ### Toggler
165
+
166
+ The Toggler class provides methods that determine whether or not new feature code is run and handles success/failure emissions. Each toggler handles one feature flag, and is created by `FlagManager.prototype.new_toggler()`.
167
+
168
+ ---
169
+
170
+ #### Instance Methods
171
+
172
+ ##### `is_flag_active()`
173
+
174
+ Checks for flag status, whitelisted users, and rollout percentage in that order to determine whether the new feature is enabled.
175
+
176
+ - If the flag's active status is false, the function returns `false`
177
+ - If current user's UUID is in the whitelist of users, the function returns `true`
178
+ - If current user's UUID hashes to a value within user rollout percentage, the function returns `true`
179
+ - If current user's UUID hashes to a value outside user rollout percentage, the function returns `false`
180
+
181
+ **Parameters:**
182
+
183
+ - `null`
184
+
185
+ **Return Value**
186
+
187
+ - `true` or `flase` depending on whether the feature flag is active
16
188
 
17
- $ bundle install
189
+ ---
18
190
 
19
- Or install it yourself as:
191
+ ##### `emit_success()`
20
192
 
21
- $ gem install tailslide
193
+ Records a successful operation to the Redis Timeseries database, with key `flagId:success` and value of current timestamp
22
194
 
23
- ## Usage
195
+ **Parameters:**
24
196
 
25
- TODO: Write usage instructions here
197
+ - `null`
26
198
 
27
- ## Development
199
+ **Return Value**
28
200
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
201
+ - `null`
30
202
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
203
+ ---
32
204
 
33
- ## Contributing
205
+ ##### `emit_failure()`
34
206
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/tailslide. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/tailslide/blob/main/CODE_OF_CONDUCT.md).
207
+ Records a failure operation to the Redis Timeseries database, with key `flagId:success` and value of current timestamp
36
208
 
37
- ## License
209
+ **Parameters:**
38
210
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
211
+ - `null`
40
212
 
41
- ## Code of Conduct
213
+ **Return Value**
42
214
 
43
- Everyone interacting in the Tailslide project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/tailslide/blob/main/CODE_OF_CONDUCT.md).
215
+ - `null`
@@ -0,0 +1,46 @@
1
+ require_relative 'nats_client'
2
+ require_relative 'redis_timeseries_client'
3
+ require_relative 'toggler'
4
+
5
+ class FlagManager
6
+
7
+ def initialize(nats_server: '', stream: '', app_id: '', sdk_key: '', user_context: '', redis_host: '', redis_port: '')
8
+ @nats_client = NatsClient.new(server_url: nats_server, stream: stream, subject: app_id, callback: method(:set_flags),
9
+ token: sdk_key)
10
+ @redis_ts_client = RedisTimeSeriesClient.new(redis_host, redis_port)
11
+ @user_context = user_context
12
+ @flags = []
13
+ end
14
+
15
+ def initialize_flags
16
+ @nats_client.initialize_flags
17
+ @redis_ts_client.init
18
+ end
19
+
20
+ def set_flags(flags)
21
+ @flags = flags
22
+ end
23
+
24
+ def get_flags
25
+ @flags
26
+ end
27
+
28
+ def set_user_context(new_user_context)
29
+ @user_context = new_user_context
30
+ end
31
+
32
+ def get_user_context
33
+ @user_context
34
+ end
35
+
36
+ def disconnect
37
+ @nats_client.disconnect
38
+ @redis_ts_client.disconnect
39
+ end
40
+
41
+ def new_toggler(config)
42
+ Toggler.new(**config, get_flags: method(:get_flags), user_context: get_user_context,
43
+ emit_redis_signal: @redis_ts_client.method(:emit_signal))
44
+ end
45
+ end
46
+
@@ -0,0 +1,60 @@
1
+ require 'async'
2
+ require 'nats/client'
3
+ TimeoutError = NATS::IO::Timeout
4
+ require 'json'
5
+
6
+ class NatsClient
7
+ attr_accessor :nats_connection, :jetstream, :subscribed_stream
8
+ attr_reader :connection_string, :stream, :subject, :callback
9
+
10
+ def initialize(server_url: 'localhost:4222', stream: '', subject: '', callback: nil, token: '')
11
+ @stream = stream
12
+ @subject = format_subject(subject)
13
+ @connection_string = "nats://#{token}#{'@' if token}#{server_url}"
14
+ @callback = callback
15
+ end
16
+
17
+ def initialize_flags
18
+ connect
19
+ fetch_latest_message
20
+ fetch_ongoing_event_messages
21
+ end
22
+
23
+ private
24
+
25
+ def connect
26
+ self.nats_connection = NATS.connect(connection_string)
27
+ self.jetstream = nats_connection.jetstream
28
+ end
29
+
30
+ def fetch_latest_message
31
+ latest_msg = jetstream.get_last_msg(stream, subject)
32
+ json_data = JSON.parse latest_msg.data
33
+ callback.call(json_data)
34
+ rescue NATS::Timeout => e
35
+ end
36
+
37
+ def fetch_ongoing_event_messages
38
+ Async do |_task|
39
+ self.subscribed_stream = jetstream.pull_subscribe(subject, 'me', config: { deliver_policy: 'new' })
40
+ begin
41
+ messages = subscribed_stream.fetch(1)
42
+ messages.each do |message|
43
+ message.ack
44
+ json_data = JSON.parse message.data
45
+ callback.call(json_data)
46
+ end
47
+ rescue NATS::IO::Timeout => e
48
+ end until nats_connection.closed?
49
+ end
50
+ end
51
+
52
+ def disconnect
53
+ nats_connection.close
54
+ end
55
+
56
+ def format_subject(subject)
57
+ "apps.#{subject}.>"
58
+ end
59
+ end
60
+
@@ -0,0 +1,22 @@
1
+ require 'redistimeseries'
2
+ using Redistimeseries::RedisRefinement
3
+
4
+ class RedisTimeSeriesClient
5
+ attr_reader :host, :port
6
+ attr_accessor :redis_client
7
+
8
+ def initialize(host, port)
9
+ @host = host || 'localhost'
10
+ @port = port || 6379
11
+ end
12
+
13
+ def init
14
+ self.redis_client = Redis.new(host: host, port: port)
15
+ end
16
+
17
+ def emit_signal(flag_id, app_id, status)
18
+ redis_client.ts_add(key: "#{flag_id}:#{status}", timestamp: '*', value: 1,
19
+ labels: ['status', status, 'appId', app_id, 'flagId', flag_id])
20
+ end
21
+ end
22
+
@@ -0,0 +1,74 @@
1
+ require 'digest'
2
+
3
+ class Toggler
4
+ attr_reader :flag_name, :get_flags, :emit_redis_signal, :user_context
5
+ attr_accessor :app_id, :flag_id
6
+
7
+ def initialize(flag_name: '', get_flags: nil, emit_redis_signal: nil, user_context: '')
8
+ @flag_name = flag_name
9
+ @get_flags = get_flags
10
+ @flag_id = nil
11
+ @app_id = nil
12
+ set_flag_id_and_app_id(flag_name)
13
+ @emit_redis_signal = emit_redis_signal
14
+ @user_context = user_context
15
+ end
16
+
17
+ def is_flag_active
18
+ flag = get_matching_flag
19
+ flag['is_active'] && (is_user_white_listed(flag) || validate_user_rollout(flag))
20
+ end
21
+
22
+ def emit_success
23
+ return unless flag_id
24
+
25
+ p 'emiting success'
26
+ emit_redis_signal.call(flag_id, app_id, 'success')
27
+ end
28
+
29
+ def emit_failure
30
+ return unless flag_id
31
+
32
+ emit_redis_signal.call(flag_id, app_id, 'failure')
33
+ end
34
+
35
+ private
36
+
37
+ def get_matching_flag
38
+ flag = get_flags.call.find { |flag| flag['title'] == flag_name }
39
+ raise Exception, "Cannot find flag with flag name of: #{flag_name}" unless flag
40
+
41
+ flag
42
+ end
43
+
44
+ def set_flag_id_and_app_id(_flag_name)
45
+ matching_flag = get_matching_flag
46
+ self.flag_id = matching_flag['id']
47
+ self.app_id = matching_flag['app_id']
48
+ end
49
+
50
+ def is_user_white_listed(flag)
51
+ flag['white_listed_users'].split(',').include?(user_context)
52
+ end
53
+
54
+ def validate_user_rollout(flag)
55
+ rollout = flag['rollout_percentage'] / 100.0
56
+ rollout *= (flag['circuit_recovery_percentage'] / 100.0) if is_circuit_in_recovery(flag)
57
+ is_user_in_rollout(rollout)
58
+ end
59
+
60
+ def is_circuit_in_recovery(flag)
61
+ flag['is_recoverable'] && flag['circuit_status'] == 'recovery'
62
+ end
63
+
64
+ def is_user_in_rollout(rollout)
65
+ puts "User context hash #{hash_user_context}"
66
+ puts "Rollout: #{rollout}"
67
+ hash_user_context <= rollout
68
+ end
69
+
70
+ def hash_user_context
71
+ (Digest::MD5.hexdigest(user_context).to_i(base = 16) % 100) / 100.0
72
+ end
73
+ end
74
+
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tailslide
4
- VERSION = "0.1.0"
4
+ VERSION = '0.1.4'
5
5
  end
data/lib/tailslide.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "tailslide/version"
4
+ require_relative "tailslide/flag_manager"
4
5
 
5
6
  module Tailslide
6
- class Error < StandardError; end
7
+ class FlagManager < FlagManager
8
+ end
7
9
  # Your code goes here...
8
10
  end
Binary file
data/test.rb ADDED
@@ -0,0 +1,132 @@
1
+ require "async"
2
+ # require "./lib/tailslide/nats_client.rb"
3
+ require_relative "lib/tailslide/flag_manager.rb"
4
+
5
+ # def logMessage(message)
6
+ # p message
7
+ # end
8
+
9
+ # config = {server_url: "localhost:4222", callback: :p, token: 'myToken', stream:"flags", subject:'1'}
10
+ app_id = "1"
11
+ flag_name = 'App 1 Flag 1'
12
+ flag_config = {"flag_name": flag_name}
13
+
14
+ config = {nats_server:'localhost:4222', stream:'flags_ruleset', app_id:app_id, sdk_key:'myToken', user_context:'375d39e6-9c3f-4f58-80bd-e5960b710295',
15
+ redis_host:'localhost', redis_port:6379}
16
+
17
+
18
+ Async do |task|
19
+ manager = FlagManager.new(**config)
20
+ manager.initialize_flags
21
+ flag_toggler = manager.new_toggler(flag_config)
22
+
23
+
24
+ if flag_toggler.is_flag_active
25
+ puts "Flag in #{app_id} with name \"#{flag_name}\" is active!"
26
+ flag_toggler.emit_success()
27
+ else
28
+ puts "Flag in #{app_id} with name \"#{flag_name}\" is not active!"
29
+ flag_toggler.emit_failure()
30
+ end
31
+
32
+ count = 0
33
+ limit = 20
34
+ while count < limit do
35
+ if rand < 1
36
+ flag_toggler.emit_success
37
+ puts "Emitting success"
38
+ else
39
+ flag_toggler.emit_failure
40
+ puts "Emitting failure"
41
+ end
42
+ sleep 1
43
+ end
44
+ end
45
+
46
+
47
+ # require "nats/client"
48
+ # require "async"
49
+ # TimeoutError = NATS::IO::Timeout
50
+ # require 'json'
51
+
52
+ # token = "myToken"
53
+
54
+ # nats_client = NATS.connect("nats://#{token}@127.0.0.1:4222")
55
+ # jet_stream = nats_client.jetstream
56
+
57
+ # # get last message
58
+ # latest_msg = jet_stream.get_last_msg("flags", "test")
59
+ # json_data = JSON.parse latest_msg.data
60
+ # p json_data
61
+
62
+
63
+ # # pull subscribe for new onging messages (workaround until Nats.rb make new update)
64
+ # subscribed_stream = jet_stream.pull_subscribe("test", 'mydurable', config: { deliver_policy: 'new' })
65
+ # Async do |task|
66
+ # task.async do
67
+ # begin
68
+ # messages = subscribed_stream.fetch(1)
69
+ # messages.each do |message|
70
+ # message.ack
71
+ # json_data = JSON.parse message.data
72
+ # p json_data
73
+ # end
74
+ # rescue NATS::Timeout => e
75
+ # p e
76
+ # end until nats_client.closed?
77
+ # end
78
+ # p "hello past async"
79
+ # end
80
+
81
+
82
+
83
+ # push subscribe for new ongoing messages
84
+ # setting deliver_policy still results in delivering all messages in "test" subject
85
+ # push_sub = jetStream.subscribe("test", {manual_ack: true, deliver_policy:"new"} ) do |msg|
86
+ # msg.ack
87
+ # puts msg.data
88
+ # end
89
+
90
+ # Get ongoing messages
91
+ # Push subscribe
92
+ # consumer_req = {
93
+ # stream_name: "test",
94
+ # config: {
95
+ # durable_name: "sample",
96
+ # deliver_policy: "new",
97
+ # ack_policy: "explicit",
98
+ # max_deliver: -1,
99
+ # replay_policy: "instant"
100
+ # }
101
+ # }
102
+
103
+ # config = NATS::JetStream::API::ConsumerConfig.new({ deliver_policy: "new" })
104
+ # Create inbox for push consumer.
105
+ # deliver = natsClient.new_inbox
106
+ # config.deliver_subject = deliver
107
+
108
+ # push_sub = jetStream.subscribe("test", {manual_ack: true, deliver_policy:"new"} ) do |msg|
109
+ # puts msg.data
110
+ # end
111
+
112
+ # cinfo = push_sub.consumer_info["config"]
113
+ # puts cinfo
114
+ # msg = push_sub.next_msg(timeout: 10000000000)
115
+ # msg.ack
116
+ # puts msg.data
117
+ # push_sub.consumer_info["config"]["deliver_policy"] = "new"
118
+ # puts cinfo
119
+
120
+ # loop do
121
+ # msgs = push_sub.next_msg()
122
+ # puts msgs.data
123
+ # rescue TimeoutError => e
124
+ # puts e
125
+ # sleep 1
126
+ # end
127
+
128
+ # js.publish("9", "Hello JetStream! 1")
129
+ # js.publish("9", "Hello JetStream! 2")
130
+ # js.publish("9", "Hello JetStream! 3")
131
+ # js.publish("9", "Hello JetStream! 4")
132
+ # js.publish("9", "Hello JetStream! Latest")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tailslide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Liou
@@ -11,8 +11,64 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2022-07-13 00:00:00.000000000 Z
15
- dependencies: []
14
+ date: 2022-08-23 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: async
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.3
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: nats-pure
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: 2.1.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: 2.1.0
44
+ - !ruby/object:Gem::Dependency
45
+ name: redis
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: 4.7.1
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: 4.7.1
58
+ - !ruby/object:Gem::Dependency
59
+ name: redistimeseries
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: 0.1.2
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: 0.1.2
16
72
  description: " Write a longer description or delete this line."
17
73
  email:
18
74
  - stevenliou@gmail.com
@@ -23,7 +79,8 @@ executables: []
23
79
  extensions: []
24
80
  extra_rdoc_files: []
25
81
  files:
26
- - ".rubocop.yml"
82
+ - ".vscode/launch.json"
83
+ - ".vscode/settings.json"
27
84
  - CHANGELOG.md
28
85
  - CODE_OF_CONDUCT.md
29
86
  - Gemfile
@@ -31,8 +88,14 @@ files:
31
88
  - README.md
32
89
  - Rakefile
33
90
  - lib/tailslide.rb
91
+ - lib/tailslide/flag_manager.rb
92
+ - lib/tailslide/nats_client.rb
93
+ - lib/tailslide/redis_timeseries_client.rb
94
+ - lib/tailslide/toggler.rb
34
95
  - lib/tailslide/version.rb
35
96
  - sig/tailslide.rbs
97
+ - tailslide-0.1.3.gem
98
+ - test.rb
36
99
  homepage: https://github.com/tailslide-io/tailslide.rb
37
100
  licenses:
38
101
  - MIT
@@ -58,5 +121,6 @@ requirements: []
58
121
  rubygems_version: 3.3.7
59
122
  signing_key:
60
123
  specification_version: 4
61
- summary: Write a short summary, because RubyGems requires one.
124
+ summary: This is the Ruby SDK for Tailslide, which is a feature flag framework with
125
+ automatic fail safe and circuit recovery.
62
126
  test_files: []
data/.rubocop.yml DELETED
@@ -1,13 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.6
3
-
4
- Style/StringLiterals:
5
- Enabled: true
6
- EnforcedStyle: double_quotes
7
-
8
- Style/StringLiteralsInInterpolation:
9
- Enabled: true
10
- EnforcedStyle: double_quotes
11
-
12
- Layout/LineLength:
13
- Max: 120