flagger 2.0.5 → 2.0.6

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: 83ee349b75c8fe210460e4d38f08a1163c26934d9d3479ee6816339f7c717b18
4
- data.tar.gz: 05aaec4dcc582463ae66d06ab01dc49f359b8177c655640550f4386ccfa92ced
3
+ metadata.gz: 7eb7e52085ab82a9d5b50780ad0a3eb53af7153fbc95f6435023573320ea2d25
4
+ data.tar.gz: d955270253eeedd0b0fcf9fc3819b6d7062419fbde90f2fa265f8928eb33c3b0
5
5
  SHA512:
6
- metadata.gz: 8a831fff34ffd437e578e7d201328fc2432364695eb09561e2e684b5f9c410dd5471e01d49f3f73a98fb4b587030d7dba8c5e62e35acf9ecce0bf496801392d9
7
- data.tar.gz: b6b765ddf6dd34c7c8b3f450f3c549b0514157f29b8d6014929000fb36d58b36c93f231f232e3b1f5f271bd544a2c90b5da4496178ed222bad1ed4f6b73b60ee
6
+ metadata.gz: 22f9b69016e460c75d2a6536f7b79894ba7a4e1b3cca6e3a7b279b3534f630cd6ef6a2651554bb6846065c3aa2f624441b4ee9f3cfd80374fb8a4c872d1d79cb
7
+ data.tar.gz: e8a2ccb1e769b0a99a693a8025c90ef7389ff36fa9845184b225c62c0af3416338bb1890ab7580ed84722707d6bd7b563d3b8a48176b1f54be0a4416a261bad4
data/lib/flagger.rb CHANGED
@@ -45,11 +45,20 @@ class Flagger
45
45
  @edge_url = options[:edge_url]
46
46
  @request_timeout = options[:request_timeout] || 10
47
47
 
48
- @delegate&.cleanup
49
- if @edge_url.nil? then
50
- @delegate = FlaggerEnvironments::CloudDelegate.new(@env_key, @request_timeout)
51
- else
52
- @delegate = FlaggerEnvironments::MicroserviceDelegate.new(@env_key, @edge_url, @request_timeout)
48
+ applied_options = {
49
+ env_key: @env_key,
50
+ edge_url: @edge_url,
51
+ request_timeout: @request_timeout
52
+ }
53
+ if not @prev_options == applied_options
54
+ @prev_options = applied_options
55
+
56
+ @delegate&.cleanup
57
+ if @edge_url.nil? then
58
+ @delegate = FlaggerEnvironments::CloudDelegate.new(@env_key, @request_timeout)
59
+ else
60
+ @delegate = FlaggerEnvironments::MicroserviceDelegate.new(@env_key, @edge_url, @request_timeout)
61
+ end
53
62
  end
54
63
  end
55
64
 
data/lib/flagger/cloud.rb CHANGED
@@ -4,6 +4,7 @@ require 'faye/websocket'
4
4
  require 'json'
5
5
  require 'lru_redux'
6
6
  require 'set'
7
+ require 'thread'
7
8
  require 'flagger/models'
8
9
  require 'flagger/stat'
9
10
  require 'flagger/version'
@@ -30,6 +31,7 @@ module FlaggerEnvironments
30
31
 
31
32
  @ingestion_max_items = 500
32
33
  @ingestion_interval = 30
34
+ @ingestion_lock = Mutex.new
33
35
 
34
36
  @entities = []
35
37
  @stats = []
@@ -57,17 +59,13 @@ module FlaggerEnvironments
57
59
  STDERR.puts 'Failed to retrieve initial gating info from CloudFront backup', e.backtrace
58
60
  end
59
61
 
60
- if EM.reactor_running? then
61
- em_subscribe_updates
62
- em_ingestion_timer
63
- else
64
- Thread.new {
65
- EM.run {
66
- em_subscribe_updates
67
- em_ingestion_timer
68
- }
69
- }
70
- end
62
+ # ensure EventMachine is running
63
+ Thread.new { EventMachine.run } unless EventMachine.reactor_running?
64
+ Thread.pass until EventMachine.reactor_running?
65
+
66
+ em_subscribe_updates
67
+ em_police_updates
68
+ em_ingestion_timer
71
69
  end
72
70
 
73
71
  def get_gating_info(url, stat_name)
@@ -93,6 +91,7 @@ module FlaggerEnvironments
93
91
 
94
92
  @ws.on :message do |event|
95
93
  begin
94
+ @last_ws_update = Time.now
96
95
  @gating_info = FlaggerModels::GatingInfo.new(JSON.parse(event.data))
97
96
  update_sdk_vars(@gating_info)
98
97
  rescue Exception => e
@@ -103,14 +102,55 @@ module FlaggerEnvironments
103
102
  @ws.on :close do |event|
104
103
  STDERR.puts ['Connection closed to Airship update server', event.code, event.reason] unless @ws_unsubbed
105
104
  EventMachine::Timer.new(5) do
106
- em_subscribe_updates
107
- end unless @ws_unsubbed
105
+ em_subscribe_updates unless @ws_unsubbed
106
+ end
108
107
  end
109
108
  end
110
109
 
111
110
  def unsubscribe_updates()
112
111
  @ws_unsubbed = true
113
- @ws.close()
112
+ @ws&.close
113
+ end
114
+
115
+ def em_police_updates
116
+ ping_timer = EventMachine::PeriodicTimer.new(5) do
117
+ if @cleaning then
118
+ ping_timer.cancel
119
+ else
120
+ @ws&.ping do
121
+ @last_ws_update = Time.now
122
+ end
123
+ end
124
+ end
125
+
126
+ police_update_timer = EventMachine::PeriodicTimer.new(30) do
127
+ if @cleaning then
128
+ police_update_timer.cancel
129
+ else
130
+ if Time.now - (@last_ws_update || Time.new(0)) > 30
131
+ STDERR.puts 'Did not receive a keepalive for more than 30 seconds. Reconnecting.'
132
+ @ws&.close
133
+ end
134
+ end
135
+ end
136
+
137
+ poll_gating_info_timer = EventMachine::PeriodicTimer.new(60) do
138
+ if @cleaning then
139
+ poll_gating_info_timer.cancel
140
+ else
141
+ if Time.now - (@last_ws_update || Time.new(0)) > 60
142
+ EM.defer(proc {
143
+ STDERR.puts 'Did not receive a keepalive for more than 60 seconds. Polling gating info.'
144
+ begin
145
+ get_gating_info("#{CLOUDFRONT_GATING_INFO_ENDPOINT}/#{@env_key}", 'duration__cloudfront_gating_info')
146
+ STDERR.puts 'Polled gating info from CloudFront'
147
+ rescue Exception => e
148
+ STDERR.puts 'Failed polling gating info from CloudFront', e.backtrace
149
+ end
150
+ })
151
+ end
152
+ end
153
+ end
114
154
  end
115
155
 
116
156
  def update_sdk_vars(gating_info)
@@ -171,41 +211,44 @@ module FlaggerEnvironments
171
211
  )
172
212
 
173
213
  if should_ingest then
174
- begin
175
- entities = @entities
176
- stats = @stats
177
- exposures = @exposures
178
- flags = @flags.to_a
179
- @entities = []
180
- @stats = []
181
- @exposures = []
182
- @ingested_flags.merge(@flags)
183
- @flags = Set[]
184
-
185
- conn = Faraday.new(url: "#{IDENTIFY_ENDPOINT}/#{@env_key}")
186
- response = conn.post do |req|
187
- req.options.timeout = @request_timeout
188
- req.headers['Content-Type'] = 'application/json'
189
- req.body = JSON.generate(
190
- {
191
- 'sdk_info' => {
192
- 'name' => 'ruby',
193
- 'version' => FlaggerUtils::VERSION
194
- },
195
- 'objects' => entities,
196
- 'stats' => stats,
197
- 'exposures' => exposures,
198
- 'flags' => flags
199
- })
200
- end
201
- if response.status != 200 then
202
- STDERR.puts 'Failed to upload entities', response.status
203
- nil
204
- end
205
- rescue Exception => e
206
- STDERR.puts 'Failed to upload entities', e
207
- nil
208
- end
214
+ entities = @entities
215
+ stats = @stats
216
+ exposures = @exposures
217
+ flags = @flags.to_a
218
+ @entities = []
219
+ @stats = []
220
+ @exposures = []
221
+ @ingested_flags.merge(@flags)
222
+ @flags = Set[]
223
+
224
+ EM.defer(
225
+ proc {
226
+ begin
227
+ conn = Faraday.new(url: "#{IDENTIFY_ENDPOINT}/#{@env_key}")
228
+ response = conn.post do |req|
229
+ req.options.timeout = @request_timeout
230
+ req.headers['Content-Type'] = 'application/json'
231
+ req.body = JSON.generate(
232
+ {
233
+ 'sdk_info' => {
234
+ 'name' => 'ruby',
235
+ 'version' => FlaggerUtils::VERSION
236
+ },
237
+ 'objects' => entities,
238
+ 'stats' => stats,
239
+ 'exposures' => exposures,
240
+ 'flags' => flags
241
+ })
242
+ end
243
+ if response.status != 200 then
244
+ STDERR.puts 'Failed to upload entities', response.status
245
+ nil
246
+ end
247
+ rescue Exception => e
248
+ STDERR.puts 'Failed to upload entities', e
249
+ nil
250
+ end
251
+ })
209
252
  end
210
253
  end
211
254
 
@@ -216,9 +259,9 @@ module FlaggerEnvironments
216
259
 
217
260
  seconds = (seconds + 1) % @ingestion_interval
218
261
  if seconds == 0 then
219
- EM.defer(proc {
262
+ @ingestion_lock.synchronize {
220
263
  maybe_ingest(true)
221
- })
264
+ }
222
265
  end
223
266
  end
224
267
  end
@@ -226,31 +269,41 @@ module FlaggerEnvironments
226
269
  def cleanup()
227
270
  @cleaning = true
228
271
  unsubscribe_updates
229
- maybe_ingest(true)
272
+ @ingestion_lock.synchronize {
273
+ maybe_ingest(true)
274
+ }
230
275
  end
231
276
 
232
277
  def save_entity(entity)
233
- if @entity_lru_hashes[entity.id] != entity.hash then
234
- @entity_lru_hashes[entity.id] = entity.hash
235
- @entities.push(entity.attrs)
236
- maybe_ingest()
237
- end
278
+ @ingestion_lock.synchronize {
279
+ if @entity_lru_hashes[entity.id] != entity.hash then
280
+ @entity_lru_hashes[entity.id] = entity.hash
281
+ @entities.push(entity.attrs)
282
+ maybe_ingest()
283
+ end
284
+ }
238
285
  end
239
286
 
240
287
  def save_stat(stat)
241
- @stats.push(stat)
242
- @stats = FlaggerUtils::Stat.compact(@stats)
243
- maybe_ingest()
288
+ @ingestion_lock.synchronize {
289
+ @stats.push(stat)
290
+ @stats = FlaggerUtils::Stat.compact(@stats)
291
+ maybe_ingest()
292
+ }
244
293
  end
245
294
 
246
295
  def save_exposure(exposure)
247
- @exposures.push(exposure)
248
- maybe_ingest()
296
+ @ingestion_lock.synchronize {
297
+ @exposures.push(exposure)
298
+ maybe_ingest()
299
+ }
249
300
  end
250
301
 
251
302
  def save_flag(flag)
252
- @flags.add(flag)
253
- maybe_ingest()
303
+ @ingestion_lock.synchronize {
304
+ @flags.add(flag)
305
+ maybe_ingest()
306
+ }
254
307
  end
255
308
 
256
309
  def stringify_keys(hash)
@@ -434,7 +487,9 @@ module FlaggerEnvironments
434
487
  identify_entity(entity)
435
488
  end
436
489
 
437
- maybe_ingest(true)
490
+ @ingestion_lock.synchronize {
491
+ maybe_ingest(true)
492
+ }
438
493
  end
439
494
  end
440
495
  end
@@ -1,4 +1,4 @@
1
1
  module FlaggerUtils
2
- VERSION = '2.0.5'
2
+ VERSION = '2.0.6'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.5
4
+ version: 2.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airship Dev Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-18 00:00:00.000000000 Z
11
+ date: 2018-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday