glowworm 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +6 -0
  3. data/.yardopts +1 -0
  4. data/Gemfile +5 -0
  5. data/Gemfile.lock +129 -0
  6. data/LICENSE +19 -0
  7. data/README.md +326 -0
  8. data/Rakefile +29 -0
  9. data/bin/basic_server_tester +311 -0
  10. data/bin/em_server/config.ru +2 -0
  11. data/bin/em_server/em_server.rb +19 -0
  12. data/bin/em_server_tester +68 -0
  13. data/bin/glowworm +90 -0
  14. data/bin/load_tester +84 -0
  15. data/ci_jobs/glowworm-continuous-deploy-next-staging/run.sh +10 -0
  16. data/ci_jobs/glowworm-integrations/run.sh +15 -0
  17. data/ci_jobs/glowworm-performance/run.sh +2 -0
  18. data/ci_jobs/glowworm-robustness/run.sh +2 -0
  19. data/ci_jobs/glowworm-units/run.sh +13 -0
  20. data/ci_jobs/setup.sh +119 -0
  21. data/example/example_server.ecology +6 -0
  22. data/example/example_server.rb +32 -0
  23. data/glowworm.gemspec +54 -0
  24. data/lib/glowworm.rb +501 -0
  25. data/lib/glowworm/em.rb +8 -0
  26. data/lib/glowworm/no_bg.rb +2 -0
  27. data/lib/glowworm/version.rb +3 -0
  28. data/server/Gemfile +27 -0
  29. data/server/Gemfile.lock +87 -0
  30. data/server/PROTOCOL +39 -0
  31. data/server/check_mk_checks/check_glowworm_server +43 -0
  32. data/server/db_migrations/20111004214649_change_feature_accounts_to_string.rb +60 -0
  33. data/server/db_migrations/20111028104546_add_value_to_account_set_features.rb +12 -0
  34. data/server/db_migrations/20120217090636_add_fully_active_flag_to_features.rb +15 -0
  35. data/server/example_test_data.rb +66 -0
  36. data/server/glowworm_server.ecology.erb +16 -0
  37. data/server/glowworm_server.rb +226 -0
  38. data/server/run/server.sh +7 -0
  39. data/server/server_test.rb +72 -0
  40. data/server/version.rb +3 -0
  41. data/test/integration/basic_server_test.rb +90 -0
  42. data/test/integration/create_sqlite_data.rb +196 -0
  43. data/test/integration/em_server_test.rb +68 -0
  44. data/test/integration/gemfile_for_specific_glowworm_version +17 -0
  45. data/test/integration/gemfile_for_specific_glowworm_version.lock +55 -0
  46. data/test/integration/integration_test_helper.rb +153 -0
  47. data/test/integration/load_test.rb +59 -0
  48. data/test/integration/nginx.conf +23 -0
  49. data/test/integration/server_test.ecology.erb +6 -0
  50. data/test/test_helper.rb +47 -0
  51. data/test/units/em_test.rb +41 -0
  52. data/test/units/feature_flag_test.rb +297 -0
  53. data/test/units/no_bg_test.rb +40 -0
  54. data/test/units/request_test.rb +51 -0
  55. metadata +410 -0
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require "bundler"
2
+ require "rake/testtask"
3
+
4
+ require File.join(File.dirname(__FILE__), "lib", "glowworm", "version")
5
+
6
+ desc "Run all tests"
7
+ task "test" => [ "test:units", "test:integration" ]
8
+
9
+ Rake::TestTask.new("test:units") do |t|
10
+ t.libs << "test"
11
+ t.test_files = Dir.glob("test/units/*test.rb")
12
+ t.verbose = true
13
+ end
14
+
15
+ Rake::TestTask.new("test:integration") do |t|
16
+ t.libs << "test"
17
+ t.test_files = Dir.glob("test/integration/*test.rb")
18
+ t.verbose = true
19
+ end
20
+
21
+ desc 'Builds the gem'
22
+ task :build do
23
+ sh "gem build glowworm.gemspec"
24
+ end
25
+
26
+ desc 'Builds and installs the gem'
27
+ task :install => :build do
28
+ sh "gem install glowworm-#{Glowworm::VERSION}"
29
+ end
@@ -0,0 +1,311 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "trollop"
4
+ OPTS = Trollop.options do
5
+ opt :server, "Glowworm server URL", :default => "localhost:4999"
6
+ opt :raise_on_assert, "Raise exception on failure", :default => false
7
+ opt :nbg, "Run Glowworm in no_bg mode", :default => false
8
+ end
9
+
10
+ require "glowworm"
11
+ Glowworm.server = OPTS[:server]
12
+ STATS = Hash.new(0)
13
+ FAKE_LOGGER = Object.new
14
+ STATS[:logger_error] = 0
15
+ STATS[:logger_warning] = 0
16
+ STATS[:logger_critical] = 0
17
+ STATS[:logger_fatal] = 0
18
+ STATS[:assert_count] = 0
19
+ STATS[:success] = 0
20
+ STATS[:failure] = 0
21
+
22
+ def FAKE_LOGGER.error(*args)
23
+ STDERR.puts("ERROR ", *args)
24
+ STATS[:logger_error] += 1
25
+ end
26
+ def FAKE_LOGGER.warn(*args)
27
+ STDERR.puts("WARN ", *args)
28
+ STATS[:logger_warning] += 1
29
+ end
30
+ def FAKE_LOGGER.critical(*args)
31
+ STDERR.puts("CRITICAL ", *args)
32
+ STATS[:logger_critical] += 1
33
+ end
34
+ def FAKE_LOGGER.fatal(*args)
35
+ STDERR.puts("FATAL ", *args)
36
+ STATS[:logger_fatal] += 1
37
+ end
38
+ def FAKE_LOGGER.debug(*args);
39
+ STDERR.puts("DEBUG ", *args)
40
+ end
41
+ def FAKE_LOGGER.info(*args);
42
+ STDERR.puts("INFO ", *args)
43
+ end
44
+
45
+ Glowworm.termite_logger = FAKE_LOGGER
46
+ Glowworm.termite_logger.debug("using ecology data: ", Ecology.data.to_s)
47
+
48
+ if OPTS[:nbg]
49
+ if Glowworm::VERSION < "0.1.6"
50
+ exit 0
51
+ end
52
+ Glowworm.no_bg
53
+ else
54
+ # Get things started
55
+ Glowworm.prefetch(:all, :all)
56
+ end
57
+
58
+ require "minitest/autorun"
59
+ require "minitest/unit"
60
+ require "minitap"
61
+
62
+ if ENV["TEST_GLOWWORM_VERSION"] && ENV["TEST_GLOWWORM_VERSION"] != "latest" && Glowworm::VERSION != ENV["TEST_GLOWWORM_VERSION"]
63
+ fail "Should be testing under #{ENV["TEST_GLOWWORM_VERSION"]}"
64
+ end
65
+
66
+ $stderr.puts "Glowworm version: #{Glowworm::VERSION}"
67
+
68
+ class Tester < MiniTest::Unit::TestCase
69
+ def test_large_timeout
70
+ if Glowworm::VERSION < "0.1.6"
71
+ assert_equal(10.0, Glowworm.timeout, "timeout must be 10.0")
72
+ elsif Glowworm.threadless
73
+ assert_equal(0.0, Glowworm.timeout, "timeout must be 0 with no bg")
74
+ else
75
+ assert_equal(10.0, Glowworm.timeout, "timeout must be 10.0")
76
+ end
77
+ end
78
+
79
+ def test_123_foo
80
+ assert Glowworm.feature_flag(123, 'foo'),
81
+ "Feature_flag(123, 'foo') should always return true on a test dataset."
82
+ end
83
+
84
+ def test_low_ttl_timeout
85
+ (1..100).each do
86
+ assert Glowworm.feature_flag(123, 'foo', :ttl => 0, :timeout => 1),
87
+ "Feature_flag(123, 'foo') should always return true on a test dataset."
88
+ sleep 0.1
89
+ end
90
+ end
91
+
92
+ ONE_HORSE_TOWN = 1
93
+ TWO_HORSE_TOWN = 2
94
+ NO_HORSE_TOWN = 3
95
+
96
+ def feature_flag_test_with_override(override, fully_active)
97
+ if Glowworm::VERSION <= "0.0.15" && nil != override
98
+ skip "glowworm 0.0.15 and less are known not to behave as expected with a override"
99
+ end
100
+
101
+ if Glowworm::VERSION <= "0.0.22" && fully_active
102
+ skip "glowworm 0.0.22 and less do not implement fully_active"
103
+ end
104
+
105
+ [[], [ONE_HORSE_TOWN], [ONE_HORSE_TOWN, TWO_HORSE_TOWN]].each do |acct_sets|
106
+ num_accts = acct_sets.size
107
+ offset = override.nil? ? 0 : (override == true ? 1 : 2)
108
+ offset += 3 if fully_active
109
+ id = 1000 + offset * 100 + num_accts
110
+ account = "account_for_acct_sets_#{num_accts}_#{override.inspect}"
111
+ feature = "#{fully_active ? "fully_active_" : ""}feature_for_acct_sets_#{num_accts}_#{override.inspect}"
112
+
113
+ actual_values = {}
114
+ actual_values[:no_default] = Glowworm.feature_flag(account, feature)
115
+ [ true, false, 5, 0, nil, :default ].each do |default_value|
116
+ actual_values[default_value] = Glowworm.feature_flag(account, feature, :default => default_value)
117
+ end
118
+
119
+ if override != nil
120
+ # If there is an override, it should always be returned
121
+ actual_values.keys.each do |value|
122
+ assert_equal override, actual_values[value],
123
+ "With override of #{override.inspect}, feature_flag(#{account.inspect}, #{feature.inspect}) " +
124
+ "default #{value.inspect} must return #{override.inspect} not #{actual_values[value].inspect}"
125
+ end
126
+ else
127
+ if num_accts == 0
128
+ # If feature isn't active for any account_sets and there's no override,
129
+ # the default should be returned.
130
+ (actual_values.keys - [:no_default]).each do |value|
131
+ assert_equal value, actual_values[value],
132
+ "With no override and no account_sets active, feature_flag must " +
133
+ "return the default value of #{value.inspect}!"
134
+ end
135
+
136
+ assert_equal fully_active, actual_values[:no_default],
137
+ "With no override, no account_sets active #{fully_active ? "a fully active feature " : ""}and no default, " +
138
+ "feature_flag must return the (default) default value of #{fully_active}!"
139
+ elsif num_accts == 1
140
+ # If feature is switched for an account_set and there's no override,
141
+ # we should return the switched value.
142
+ actual_values.keys.each do |value|
143
+ assert_equal true, actual_values[value],
144
+ "With no override and one acct set active, feature_flag must " +
145
+ "return true!"
146
+ end
147
+ elsif num_accts == 2
148
+ # If feature is switched for two account_sets and there's no override,
149
+ # we should return the switched value.
150
+ actual_values.keys.each do |value|
151
+ assert_equal true, actual_values[value],
152
+ "With no override and two acct sets active, feature_flag must " +
153
+ "return true!"
154
+ end
155
+ else
156
+ raise "How many account sets are you testing, anyway?"
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ def self.add_feature_flag_test_with_override(override, fully_active)
163
+ instance_eval do
164
+ define_method "test_#{fully_active ? "fully_active_" : ""}feature_flag_with_override_#{override.inspect}" do
165
+ feature_flag_test_with_override(override, fully_active)
166
+ end
167
+ end
168
+ end
169
+
170
+ # test feature flags with various override settings
171
+ [nil, true, false].product([false, true]).each do |override, fully_active|
172
+ add_feature_flag_test_with_override(override, fully_active)
173
+ end
174
+
175
+ # Get_value testing loop
176
+
177
+ LOW_ID_SET = 4
178
+ BIG_VALUE_SET = 5
179
+ LITTLE_VALUE_SET = 6
180
+
181
+ VALUE_FOR_ACCT_SET = {
182
+ ONE_HORSE_TOWN => 1,
183
+ TWO_HORSE_TOWN => 2,
184
+ BIG_VALUE_SET => 100,
185
+ LITTLE_VALUE_SET => 7,
186
+ LOW_ID_SET => 21,
187
+ }
188
+
189
+ def feature_value_test_with_override(override)
190
+ if Glowworm::VERSION <= "0.0.15" && nil != override
191
+ skip "glowworm 0.0.15 and less are known not to behave as expected with a override"
192
+ elsif Glowworm::VERSION < "0.1.4" && nil == override
193
+ skip "glowworm 0.1.2 and less are known not to behave as expected for a feature value in multiple sets"
194
+ end
195
+
196
+ counter = 0
197
+ [[],
198
+ [LITTLE_VALUE_SET],
199
+ [BIG_VALUE_SET, LITTLE_VALUE_SET],
200
+ [BIG_VALUE_SET, LITTLE_VALUE_SET, LOW_ID_SET]].each do |acct_sets|
201
+ acct_key = acct_sets.map(&:to_s).join("/")
202
+ id = 2000 + (override.nil? ? 0 : override + 1) * 100 + counter
203
+ counter += 1
204
+ account = "account_for_value_acct_sets_#{acct_key}_#{override.inspect}"
205
+ feature = "feature_for_value_acct_sets_#{acct_key}_#{override.inspect}"
206
+
207
+ actual_values = {}
208
+ actual_values[:no_default] = Glowworm.feature_flag(account, feature, :get_value => true)
209
+ assert_equal actual_values[:no_default], Glowworm.feature_value(account, feature),
210
+ "Glowworm must return the same value for .feature_value and .feature_flag(:get_value => true)!"
211
+ [ true, false, 5, 0, :default ].each do |default_value|
212
+ actual_values[default_value] = Glowworm.feature_flag(account, feature,
213
+ :default => default_value, :get_value => true)
214
+ assert_equal actual_values[default_value], Glowworm.feature_value(account, feature,
215
+ :default => default_value),
216
+ "Glowworm must return the same value for .feature_value and .feature_flag(:get_value => true)!"
217
+ end
218
+
219
+ if override != nil
220
+ # If there is an override, it should always be returned
221
+ actual_values.keys.each do |value|
222
+ assert_equal override, actual_values[value],
223
+ "With override of #{override.inspect}, feature_value(#{account.inspect}, #{feature.inspect}) " +
224
+ "default #{value.inspect} must return #{override.inspect} not #{actual_values[value].inspect}"
225
+ end
226
+ elsif acct_sets == []
227
+ # If feature isn't active for any account_sets and there's no override,
228
+ # the default should be returned.
229
+ (actual_values.keys - [:no_default]).each do |value|
230
+ assert_equal value, actual_values[value],
231
+ "With no override and no account_sets active, feature_value must " +
232
+ "return the default value of #{value.inspect}!"
233
+ end
234
+
235
+ assert_equal false, actual_values[:no_default],
236
+ "With no override, no account_sets active and no default, feature_value must " +
237
+ "return the (default) default value of false!"
238
+ elsif acct_sets.include?(LOW_ID_SET)
239
+ # If the feature is active for the set with the lowest
240
+ # account_set id and there's no override, it must return the
241
+ # value for that account_set id.
242
+ actual_values.keys.each do |value|
243
+ assert_equal VALUE_FOR_ACCT_SET[LOW_ID_SET], actual_values[value],
244
+ "With no override and the lowest-id account_set active, feature_value must " +
245
+ "return that account_set's value of #{VALUE_FOR_ACCT_SET[LOW_ID_SET]}!"
246
+ end
247
+ elsif acct_sets.include?(BIG_VALUE_SET)
248
+ # If the feature is active for the set with a lower account_set
249
+ # id and there's no override, it must return the value for that
250
+ # account_set id.
251
+ actual_values.keys.each do |value|
252
+ assert_equal VALUE_FOR_ACCT_SET[BIG_VALUE_SET], actual_values[value],
253
+ "With no override and the lowest-id account_set active, feature_value must " +
254
+ "return that account_set's value of #{VALUE_FOR_ACCT_SET[BIG_VALUE_SET]}!"
255
+ end
256
+ elsif acct_sets.include?(LITTLE_VALUE_SET)
257
+ # If the feature is active for the set with a lower account_set
258
+ # id and there's no override, it must return the value for that
259
+ # account_set id.
260
+ actual_values.keys.each do |value|
261
+ STDERR.puts "With no override and the lowest-id account_set active, feature_value must " +
262
+ "return that account_set's value of #{VALUE_FOR_ACCT_SET[LITTLE_VALUE_SET]}. " +
263
+ "Actual value returned is #{actual_values[value]}"
264
+ end
265
+ else
266
+ raise "You're testing some set of accounts I don't recognize!"
267
+ end
268
+ end
269
+ end
270
+
271
+ def self.add_feature_value_test_with_override(override)
272
+ instance_eval do
273
+ define_method "test_feature_value_with_override_#{override.inspect}" do
274
+ feature_value_test_with_override(override)
275
+ end
276
+ end
277
+ end
278
+
279
+ # Basic testing loop...
280
+ [nil, 0, 1, 2, 5].each do |override|
281
+ add_feature_value_test_with_override(override)
282
+ end
283
+ end
284
+
285
+ module MiniTest::Assertions
286
+ alias :old_assert :assert
287
+ def assert(test, msg = nil)
288
+ STATS[:assert_count] += 1
289
+ begin
290
+ old_assert(test, msg)
291
+ STATS[:success] += 1
292
+ rescue MiniTest::Assertion
293
+ STATS[:failure] += 1
294
+ raise
295
+ end
296
+ end
297
+ end
298
+
299
+ MiniTest::Unit.runner = MiniTest::TapY.new
300
+
301
+ # Output STATS to STDERR for easy debugging
302
+ MiniTest::Unit.after_tests do
303
+ STDERR.puts "Success: #{STATS[:success]}"
304
+ STDERR.puts "Failure: #{STATS[:failure]}"
305
+ STDERR.puts "Assert Count: #{STATS[:assert_count]}"
306
+ STDERR.puts "Logger warning: #{STATS[:logger_warning]}"
307
+ STDERR.puts "Logger error: #{STATS[:logger_error]}"
308
+ STDERR.puts "Logger critical: #{STATS[:logger_critical]}"
309
+ STDERR.puts "Logger fatal: #{STATS[:logger_fatal]}"
310
+ end
311
+
@@ -0,0 +1,2 @@
1
+ require "./bin/em_server/em_server"
2
+ run EMServer
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ require "thin"
3
+ require "sinatra/base"
4
+ require "glowworm/em"
5
+ require "sinatra/synchrony"
6
+
7
+ class EMServer < Sinatra::Base
8
+ register Sinatra::Synchrony
9
+
10
+ get "/update" do
11
+ Glowworm.update_cache_in_foreground
12
+ "updated!"
13
+ end
14
+
15
+ get "/" do
16
+ val = Glowworm.feature_value(123, "foo")
17
+ val.to_s
18
+ end
19
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "net/http"
4
+ require "minitest/autorun"
5
+ require "minitest/unit"
6
+ require "minitap"
7
+ require "trollop"
8
+ require "httparty"
9
+
10
+ OPTS = Trollop.options do
11
+ opt :server, "EM server URL", :type => String
12
+ end
13
+
14
+ STATS = Hash.new(0)
15
+ STATS[:logger_error] = 0
16
+ STATS[:logger_warning] = 0
17
+ STATS[:logger_critical] = 0
18
+ STATS[:logger_fatal] = 0
19
+ STATS[:assert_count] = 0
20
+ STATS[:success] = 0
21
+ STATS[:failure] = 0
22
+
23
+ class Tester < MiniTest::Unit::TestCase
24
+ def test_em_get
25
+ begin
26
+ url = OPTS[:server]
27
+ assert_equal "1", HTTParty.get(url).to_s, "Request should return 1"
28
+ rescue
29
+ assert false, "request to #{url} failed"
30
+ end
31
+ end
32
+
33
+ def test_em_update
34
+ begin
35
+ url = OPTS[:server] + "/update"
36
+ assert_equal "updated!", HTTParty.get(url).to_s, "Update should succeed"
37
+ rescue
38
+ assert false, "request to #{url} failed"
39
+ end
40
+ end
41
+ end
42
+
43
+ module MiniTest::Assertions
44
+ alias :old_assert :assert
45
+ def assert(test, msg = nil)
46
+ STATS[:assert_count] += 1
47
+ begin
48
+ old_assert(test, msg)
49
+ STATS[:success] += 1
50
+ rescue MiniTest::Assertion
51
+ STATS[:failure] += 1
52
+ raise
53
+ end
54
+ end
55
+ end
56
+
57
+ MiniTest::Unit.runner = MiniTest::TapY.new
58
+
59
+ # Output STATS to STDERR for easy debugging
60
+ MiniTest::Unit.after_tests do
61
+ STDERR.puts "Success: #{STATS[:success]}"
62
+ STDERR.puts "Failure: #{STATS[:failure]}"
63
+ STDERR.puts "Assert Count: #{STATS[:assert_count]}"
64
+ STDERR.puts "Logger warning: #{STATS[:logger_warning]}"
65
+ STDERR.puts "Logger error: #{STATS[:logger_error]}"
66
+ STDERR.puts "Logger critical: #{STATS[:logger_critical]}"
67
+ STDERR.puts "Logger fatal: #{STATS[:logger_fatal]}"
68
+ end
data/bin/glowworm ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "trollop"
4
+ require "pp"
5
+ require "glowworm"
6
+
7
+ opts = Trollop::options do
8
+ opt :feature, "What feature name to query", :type => String, :default => "video_rec"
9
+ opt :account, "What account to query", :type => String, :default => "35"
10
+ opt :debug, "Whether to debug", :type => :boolean, :default => false
11
+ opt :dump_cache, "Whether to dump the Glowworm cache", :type => :boolean, :default => false
12
+ opt :load_test, "How many times to repeat the query", :type => :int, :default => 1
13
+ banner <<BANNER
14
+ Glowworm is a program to query the feature flags of accounts and providers.
15
+
16
+ Usage: #{$0} [options] [server name]
17
+
18
+ With a specific feature and account, Glowworm will print true or false, or
19
+ raise an exception if data can't be gotten.
20
+
21
+ You can specify "all" for the --feature or --account parameters to query all.
22
+ Doing both will dump a *lot* of data, so redirect to a file.
23
+
24
+ Options:
25
+ BANNER
26
+ end
27
+
28
+ # Fake logger that ignores all calls
29
+ fake_logger = Object.new
30
+ def fake_logger.method_missing(*args); end
31
+ sensitive_logger = ::Termite::Logger.new(STDOUT)
32
+ sensitive_logger.level = ::Logger::INFO
33
+
34
+ Glowworm.server = ARGV.pop || "localhost:4999"
35
+ Glowworm.timeout = 5.0 # 5-second timeout by default
36
+ Glowworm.termite_logger = opts[:debug] ? sensitive_logger : fake_logger
37
+ Ecology.read # No ecology, must set options manually.
38
+
39
+ if opts[:debug]
40
+ puts <<END
41
+ Glowworm v#{Glowworm::VERSION}
42
+ Querying server #{Glowworm.server}
43
+ Feature #{opts[:feature]}, account #{opts[:account]}
44
+ END
45
+ end
46
+
47
+ opts[:account] = :all if opts[:account] == "all"
48
+ opts[:feature] = :all if opts[:feature] == "all"
49
+
50
+ if opts[:account] == :all || opts[:feature] == :all
51
+ puts "Prefetching: #{opts[:account]}, #{opts[:feature]}" if opts[:debug]
52
+ Glowworm.prefetch opts[:account], opts[:feature]
53
+
54
+ # Prefetch is instant, so we need to wait until the prefetch returns
55
+ Glowworm.feature_flag("fake_acct", "fake_flag")
56
+
57
+ accounts = opts[:account] == :all ? Glowworm.all_cached_accounts : [ opts[:account] ]
58
+ features = opts[:feature] == :all ? Glowworm.all_cached_features : [ opts[:feature] ]
59
+
60
+ STDERR.puts "Accounts: #{accounts.inspect}" if opts[:debug]
61
+ STDERR.puts "Features: #{features.inspect}" if opts[:debug]
62
+
63
+ cached_features = {}
64
+ accounts.each do |account|
65
+ cached_features[account] = {}
66
+ features.each do |feature|
67
+ flag = Glowworm.feature_flag(account, feature, :ttl => 1_000_000, :timeout => 0.0)
68
+ cached_features[account][feature] = flag
69
+ end
70
+ end
71
+
72
+ pp cached_features
73
+ else
74
+ opts[:load_test].times do
75
+ # 0 TTL means "always actually fetch, never treat as fresh"
76
+ puts "Querying #{Glowworm.server}, feature #{opts[:feature]}, account #{opts[:account]}:"
77
+ puts Glowworm.feature_flag(opts[:account], opts[:feature], :ttl => 0.0).inspect
78
+ end
79
+ end
80
+
81
+ if opts[:dump_cache]
82
+ puts "*************** Dumping Glowworm Cache: ****************"
83
+ puts "\nGlowworm feature cache:"
84
+ pp Glowworm.feature_cache
85
+ puts "\nGlowworm account_set cache:"
86
+ pp Glowworm.account_set_cache
87
+ puts "\nGlowworm override cache:"
88
+ pp Glowworm.override_cache
89
+ puts "********************************************************"
90
+ end