launchdarkly-server-sdk 8.11.2-java → 8.12.0-java
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 +4 -4
- data/lib/ldclient-rb/config.rb +69 -9
- data/lib/ldclient-rb/context.rb +1 -1
- data/lib/ldclient-rb/data_system.rb +227 -0
- data/lib/ldclient-rb/events.rb +34 -19
- data/lib/ldclient-rb/flags_state.rb +1 -1
- data/lib/ldclient-rb/impl/big_segments.rb +4 -4
- data/lib/ldclient-rb/impl/cache_store.rb +44 -0
- data/lib/ldclient-rb/impl/data_source/polling.rb +108 -0
- data/lib/ldclient-rb/impl/data_source/requestor.rb +113 -0
- data/lib/ldclient-rb/impl/data_source/status_provider.rb +83 -0
- data/lib/ldclient-rb/impl/data_source/stream.rb +198 -0
- data/lib/ldclient-rb/impl/data_source.rb +3 -3
- data/lib/ldclient-rb/impl/data_store/data_kind.rb +108 -0
- data/lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb +187 -0
- data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +130 -0
- data/lib/ldclient-rb/impl/data_store/status_provider.rb +76 -0
- data/lib/ldclient-rb/impl/data_store/store.rb +371 -0
- data/lib/ldclient-rb/impl/data_store.rb +11 -97
- data/lib/ldclient-rb/impl/data_system/data_source_builder_common.rb +77 -0
- data/lib/ldclient-rb/impl/data_system/fdv1.rb +20 -7
- data/lib/ldclient-rb/impl/data_system/fdv2.rb +472 -0
- data/lib/ldclient-rb/impl/data_system/http_config_options.rb +32 -0
- data/lib/ldclient-rb/impl/data_system/polling.rb +628 -0
- data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
- data/lib/ldclient-rb/impl/data_system/streaming.rb +401 -0
- data/lib/ldclient-rb/impl/dependency_tracker.rb +21 -9
- data/lib/ldclient-rb/impl/evaluator.rb +3 -2
- data/lib/ldclient-rb/impl/event_sender.rb +14 -6
- data/lib/ldclient-rb/impl/expiring_cache.rb +79 -0
- data/lib/ldclient-rb/impl/integrations/file_data_source.rb +8 -8
- data/lib/ldclient-rb/impl/integrations/file_data_source_v2.rb +460 -0
- data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +290 -0
- data/lib/ldclient-rb/impl/memoized_value.rb +34 -0
- data/lib/ldclient-rb/impl/migrations/migrator.rb +2 -1
- data/lib/ldclient-rb/impl/migrations/tracker.rb +2 -1
- data/lib/ldclient-rb/impl/model/serialization.rb +6 -6
- data/lib/ldclient-rb/impl/non_blocking_thread_pool.rb +48 -0
- data/lib/ldclient-rb/impl/repeating_task.rb +2 -2
- data/lib/ldclient-rb/impl/simple_lru_cache.rb +27 -0
- data/lib/ldclient-rb/impl/store_data_set_sorter.rb +1 -1
- data/lib/ldclient-rb/impl/util.rb +71 -0
- data/lib/ldclient-rb/impl.rb +1 -2
- data/lib/ldclient-rb/in_memory_store.rb +1 -18
- data/lib/ldclient-rb/integrations/file_data.rb +67 -0
- data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +9 -9
- data/lib/ldclient-rb/integrations/test_data.rb +11 -11
- data/lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb +582 -0
- data/lib/ldclient-rb/integrations/test_data_v2.rb +254 -0
- data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
- data/lib/ldclient-rb/interfaces/data_system.rb +704 -0
- data/lib/ldclient-rb/interfaces/feature_store.rb +5 -2
- data/lib/ldclient-rb/ldclient.rb +66 -132
- data/lib/ldclient-rb/util.rb +11 -70
- data/lib/ldclient-rb/version.rb +1 -1
- data/lib/ldclient-rb.rb +9 -17
- metadata +41 -19
- data/lib/ldclient-rb/cache_store.rb +0 -45
- data/lib/ldclient-rb/expiring_cache.rb +0 -77
- data/lib/ldclient-rb/memoized_value.rb +0 -32
- data/lib/ldclient-rb/non_blocking_thread_pool.rb +0 -46
- data/lib/ldclient-rb/polling.rb +0 -102
- data/lib/ldclient-rb/requestor.rb +0 -102
- data/lib/ldclient-rb/simple_lru_cache.rb +0 -25
- data/lib/ldclient-rb/stream.rb +0 -197
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: launchdarkly-server-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.12.0
|
|
5
5
|
platform: java
|
|
6
6
|
authors:
|
|
7
7
|
- LaunchDarkly
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-01-30 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: aws-sdk-dynamodb
|
|
@@ -271,14 +271,14 @@ dependencies:
|
|
|
271
271
|
requirements:
|
|
272
272
|
- - '='
|
|
273
273
|
- !ruby/object:Gem::Version
|
|
274
|
-
version: 2.
|
|
274
|
+
version: 2.5.0
|
|
275
275
|
type: :runtime
|
|
276
276
|
prerelease: false
|
|
277
277
|
version_requirements: !ruby/object:Gem::Requirement
|
|
278
278
|
requirements:
|
|
279
279
|
- - '='
|
|
280
280
|
- !ruby/object:Gem::Version
|
|
281
|
-
version: 2.
|
|
281
|
+
version: 2.5.0
|
|
282
282
|
- !ruby/object:Gem::Dependency
|
|
283
283
|
name: observer
|
|
284
284
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -297,22 +297,22 @@ dependencies:
|
|
|
297
297
|
name: openssl
|
|
298
298
|
requirement: !ruby/object:Gem::Requirement
|
|
299
299
|
requirements:
|
|
300
|
-
- - "~>"
|
|
301
|
-
- !ruby/object:Gem::Version
|
|
302
|
-
version: '3.1'
|
|
303
300
|
- - ">="
|
|
304
301
|
- !ruby/object:Gem::Version
|
|
305
302
|
version: 3.1.2
|
|
303
|
+
- - "<"
|
|
304
|
+
- !ruby/object:Gem::Version
|
|
305
|
+
version: '5.0'
|
|
306
306
|
type: :runtime
|
|
307
307
|
prerelease: false
|
|
308
308
|
version_requirements: !ruby/object:Gem::Requirement
|
|
309
309
|
requirements:
|
|
310
|
-
- - "~>"
|
|
311
|
-
- !ruby/object:Gem::Version
|
|
312
|
-
version: '3.1'
|
|
313
310
|
- - ">="
|
|
314
311
|
- !ruby/object:Gem::Version
|
|
315
312
|
version: 3.1.2
|
|
313
|
+
- - "<"
|
|
314
|
+
- !ruby/object:Gem::Version
|
|
315
|
+
version: '5.0'
|
|
316
316
|
- !ruby/object:Gem::Dependency
|
|
317
317
|
name: semantic
|
|
318
318
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -372,23 +372,38 @@ files:
|
|
|
372
372
|
- README.md
|
|
373
373
|
- lib/launchdarkly-server-sdk.rb
|
|
374
374
|
- lib/ldclient-rb.rb
|
|
375
|
-
- lib/ldclient-rb/cache_store.rb
|
|
376
375
|
- lib/ldclient-rb/config.rb
|
|
377
376
|
- lib/ldclient-rb/context.rb
|
|
377
|
+
- lib/ldclient-rb/data_system.rb
|
|
378
378
|
- lib/ldclient-rb/evaluation_detail.rb
|
|
379
379
|
- lib/ldclient-rb/events.rb
|
|
380
|
-
- lib/ldclient-rb/expiring_cache.rb
|
|
381
380
|
- lib/ldclient-rb/flags_state.rb
|
|
382
381
|
- lib/ldclient-rb/impl.rb
|
|
383
382
|
- lib/ldclient-rb/impl/big_segments.rb
|
|
384
383
|
- lib/ldclient-rb/impl/broadcaster.rb
|
|
384
|
+
- lib/ldclient-rb/impl/cache_store.rb
|
|
385
385
|
- lib/ldclient-rb/impl/context.rb
|
|
386
386
|
- lib/ldclient-rb/impl/context_filter.rb
|
|
387
387
|
- lib/ldclient-rb/impl/data_source.rb
|
|
388
388
|
- lib/ldclient-rb/impl/data_source/null_processor.rb
|
|
389
|
+
- lib/ldclient-rb/impl/data_source/polling.rb
|
|
390
|
+
- lib/ldclient-rb/impl/data_source/requestor.rb
|
|
391
|
+
- lib/ldclient-rb/impl/data_source/status_provider.rb
|
|
392
|
+
- lib/ldclient-rb/impl/data_source/stream.rb
|
|
389
393
|
- lib/ldclient-rb/impl/data_store.rb
|
|
394
|
+
- lib/ldclient-rb/impl/data_store/data_kind.rb
|
|
395
|
+
- lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb
|
|
396
|
+
- lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb
|
|
397
|
+
- lib/ldclient-rb/impl/data_store/status_provider.rb
|
|
398
|
+
- lib/ldclient-rb/impl/data_store/store.rb
|
|
390
399
|
- lib/ldclient-rb/impl/data_system.rb
|
|
400
|
+
- lib/ldclient-rb/impl/data_system/data_source_builder_common.rb
|
|
391
401
|
- lib/ldclient-rb/impl/data_system/fdv1.rb
|
|
402
|
+
- lib/ldclient-rb/impl/data_system/fdv2.rb
|
|
403
|
+
- lib/ldclient-rb/impl/data_system/http_config_options.rb
|
|
404
|
+
- lib/ldclient-rb/impl/data_system/polling.rb
|
|
405
|
+
- lib/ldclient-rb/impl/data_system/protocolv2.rb
|
|
406
|
+
- lib/ldclient-rb/impl/data_system/streaming.rb
|
|
392
407
|
- lib/ldclient-rb/impl/dependency_tracker.rb
|
|
393
408
|
- lib/ldclient-rb/impl/diagnostic_events.rb
|
|
394
409
|
- lib/ldclient-rb/impl/evaluation_with_hook_result.rb
|
|
@@ -399,12 +414,16 @@ files:
|
|
|
399
414
|
- lib/ldclient-rb/impl/event_sender.rb
|
|
400
415
|
- lib/ldclient-rb/impl/event_summarizer.rb
|
|
401
416
|
- lib/ldclient-rb/impl/event_types.rb
|
|
417
|
+
- lib/ldclient-rb/impl/expiring_cache.rb
|
|
402
418
|
- lib/ldclient-rb/impl/flag_tracker.rb
|
|
403
419
|
- lib/ldclient-rb/impl/integrations/consul_impl.rb
|
|
404
420
|
- lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
|
|
405
421
|
- lib/ldclient-rb/impl/integrations/file_data_source.rb
|
|
422
|
+
- lib/ldclient-rb/impl/integrations/file_data_source_v2.rb
|
|
406
423
|
- lib/ldclient-rb/impl/integrations/redis_impl.rb
|
|
407
424
|
- lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb
|
|
425
|
+
- lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb
|
|
426
|
+
- lib/ldclient-rb/impl/memoized_value.rb
|
|
408
427
|
- lib/ldclient-rb/impl/migrations/migrator.rb
|
|
409
428
|
- lib/ldclient-rb/impl/migrations/tracker.rb
|
|
410
429
|
- lib/ldclient-rb/impl/model/clause.rb
|
|
@@ -412,8 +431,10 @@ files:
|
|
|
412
431
|
- lib/ldclient-rb/impl/model/preprocessed_data.rb
|
|
413
432
|
- lib/ldclient-rb/impl/model/segment.rb
|
|
414
433
|
- lib/ldclient-rb/impl/model/serialization.rb
|
|
434
|
+
- lib/ldclient-rb/impl/non_blocking_thread_pool.rb
|
|
415
435
|
- lib/ldclient-rb/impl/repeating_task.rb
|
|
416
436
|
- lib/ldclient-rb/impl/sampler.rb
|
|
437
|
+
- lib/ldclient-rb/impl/simple_lru_cache.rb
|
|
417
438
|
- lib/ldclient-rb/impl/store_client_wrapper.rb
|
|
418
439
|
- lib/ldclient-rb/impl/store_data_set_sorter.rb
|
|
419
440
|
- lib/ldclient-rb/impl/unbounded_pool.rb
|
|
@@ -426,31 +447,32 @@ files:
|
|
|
426
447
|
- lib/ldclient-rb/integrations/redis.rb
|
|
427
448
|
- lib/ldclient-rb/integrations/test_data.rb
|
|
428
449
|
- lib/ldclient-rb/integrations/test_data/flag_builder.rb
|
|
450
|
+
- lib/ldclient-rb/integrations/test_data_v2.rb
|
|
451
|
+
- lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb
|
|
429
452
|
- lib/ldclient-rb/integrations/util/store_wrapper.rb
|
|
430
453
|
- lib/ldclient-rb/interfaces.rb
|
|
431
454
|
- lib/ldclient-rb/interfaces/big_segment_store.rb
|
|
432
455
|
- lib/ldclient-rb/interfaces/data_source.rb
|
|
433
456
|
- lib/ldclient-rb/interfaces/data_store.rb
|
|
457
|
+
- lib/ldclient-rb/interfaces/data_system.rb
|
|
434
458
|
- lib/ldclient-rb/interfaces/feature_store.rb
|
|
435
459
|
- lib/ldclient-rb/interfaces/flag_tracker.rb
|
|
436
460
|
- lib/ldclient-rb/interfaces/hooks.rb
|
|
437
461
|
- lib/ldclient-rb/interfaces/migrations.rb
|
|
438
462
|
- lib/ldclient-rb/interfaces/plugins.rb
|
|
439
463
|
- lib/ldclient-rb/ldclient.rb
|
|
440
|
-
- lib/ldclient-rb/memoized_value.rb
|
|
441
464
|
- lib/ldclient-rb/migrations.rb
|
|
442
|
-
- lib/ldclient-rb/non_blocking_thread_pool.rb
|
|
443
|
-
- lib/ldclient-rb/polling.rb
|
|
444
465
|
- lib/ldclient-rb/reference.rb
|
|
445
|
-
- lib/ldclient-rb/requestor.rb
|
|
446
|
-
- lib/ldclient-rb/simple_lru_cache.rb
|
|
447
|
-
- lib/ldclient-rb/stream.rb
|
|
448
466
|
- lib/ldclient-rb/util.rb
|
|
449
467
|
- lib/ldclient-rb/version.rb
|
|
450
468
|
homepage: https://github.com/launchdarkly/ruby-server-sdk
|
|
451
469
|
licenses:
|
|
452
470
|
- Apache-2.0
|
|
453
|
-
metadata:
|
|
471
|
+
metadata:
|
|
472
|
+
bug_tracker_uri: https://github.com/launchdarkly/ruby-server-sdk/issues
|
|
473
|
+
changelog_uri: https://github.com/launchdarkly/ruby-server-sdk/blob/main/CHANGELOG.md
|
|
474
|
+
homepage_uri: https://github.com/launchdarkly/ruby-server-sdk
|
|
475
|
+
source_code_uri: https://github.com/launchdarkly/ruby-server-sdk
|
|
454
476
|
rdoc_options: []
|
|
455
477
|
require_paths:
|
|
456
478
|
- lib
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
require "concurrent/map"
|
|
2
|
-
|
|
3
|
-
module LaunchDarkly
|
|
4
|
-
#
|
|
5
|
-
# A thread-safe in-memory store that uses the same semantics that Faraday would expect, although we
|
|
6
|
-
# no longer use Faraday. This is used by Requestor, when we are not in a Rails environment.
|
|
7
|
-
#
|
|
8
|
-
# @private
|
|
9
|
-
#
|
|
10
|
-
class ThreadSafeMemoryStore
|
|
11
|
-
#
|
|
12
|
-
# Default constructor
|
|
13
|
-
#
|
|
14
|
-
# @return [ThreadSafeMemoryStore] a new store
|
|
15
|
-
def initialize
|
|
16
|
-
@cache = Concurrent::Map.new
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
# Read a value from the cache
|
|
21
|
-
# @param key [Object] the cache key
|
|
22
|
-
#
|
|
23
|
-
# @return [Object] the cache value
|
|
24
|
-
def read(key)
|
|
25
|
-
@cache[key]
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
#
|
|
29
|
-
# Store a value in the cache
|
|
30
|
-
# @param key [Object] the cache key
|
|
31
|
-
# @param value [Object] the value to associate with the key
|
|
32
|
-
#
|
|
33
|
-
# @return [Object] the value
|
|
34
|
-
def write(key, value)
|
|
35
|
-
@cache[key] = value
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
# Delete a value in the cache
|
|
40
|
-
# @param key [Object] the cache key
|
|
41
|
-
def delete(key)
|
|
42
|
-
@cache.delete(key)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module LaunchDarkly
|
|
3
|
-
# A thread-safe cache with maximum number of entries and TTL.
|
|
4
|
-
# Adapted from https://github.com/SamSaffron/lru_redux/blob/master/lib/lru_redux/ttl/cache.rb
|
|
5
|
-
# under MIT license with the following changes:
|
|
6
|
-
# * made thread-safe
|
|
7
|
-
# * removed many unused methods
|
|
8
|
-
# * reading a key does not reset its expiration time, only writing
|
|
9
|
-
# @private
|
|
10
|
-
class ExpiringCache
|
|
11
|
-
def initialize(max_size, ttl)
|
|
12
|
-
@max_size = max_size
|
|
13
|
-
@ttl = ttl
|
|
14
|
-
@data_lru = {}
|
|
15
|
-
@data_ttl = {}
|
|
16
|
-
@lock = Mutex.new
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def [](key)
|
|
20
|
-
@lock.synchronize do
|
|
21
|
-
ttl_evict
|
|
22
|
-
@data_lru[key]
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def []=(key, val)
|
|
27
|
-
@lock.synchronize do
|
|
28
|
-
ttl_evict
|
|
29
|
-
|
|
30
|
-
@data_lru.delete(key)
|
|
31
|
-
@data_ttl.delete(key)
|
|
32
|
-
|
|
33
|
-
@data_lru[key] = val
|
|
34
|
-
@data_ttl[key] = Time.now.to_f
|
|
35
|
-
|
|
36
|
-
if @data_lru.size > @max_size
|
|
37
|
-
key, _ = @data_lru.first # hashes have a FIFO ordering in Ruby
|
|
38
|
-
|
|
39
|
-
@data_ttl.delete(key)
|
|
40
|
-
@data_lru.delete(key)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
val
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def delete(key)
|
|
48
|
-
@lock.synchronize do
|
|
49
|
-
ttl_evict
|
|
50
|
-
|
|
51
|
-
@data_lru.delete(key)
|
|
52
|
-
@data_ttl.delete(key)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def clear
|
|
57
|
-
@lock.synchronize do
|
|
58
|
-
@data_lru.clear
|
|
59
|
-
@data_ttl.clear
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def ttl_evict
|
|
66
|
-
ttl_horizon = Time.now.to_f - @ttl
|
|
67
|
-
key, time = @data_ttl.first
|
|
68
|
-
|
|
69
|
-
until time.nil? || time > ttl_horizon
|
|
70
|
-
@data_ttl.delete(key)
|
|
71
|
-
@data_lru.delete(key)
|
|
72
|
-
|
|
73
|
-
key, time = @data_ttl.first
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module LaunchDarkly
|
|
3
|
-
# Simple implementation of a thread-safe memoized value whose generator function will never be
|
|
4
|
-
# run more than once, and whose value can be overridden by explicit assignment.
|
|
5
|
-
# Note that we no longer use this class and it will be removed in a future version.
|
|
6
|
-
# @private
|
|
7
|
-
class MemoizedValue
|
|
8
|
-
def initialize(&generator)
|
|
9
|
-
@generator = generator
|
|
10
|
-
@mutex = Mutex.new
|
|
11
|
-
@inited = false
|
|
12
|
-
@value = nil
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def get
|
|
16
|
-
@mutex.synchronize do
|
|
17
|
-
unless @inited
|
|
18
|
-
@value = @generator.call
|
|
19
|
-
@inited = true
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
@value
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def set(value)
|
|
26
|
-
@mutex.synchronize do
|
|
27
|
-
@value = value
|
|
28
|
-
@inited = true
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require "concurrent"
|
|
2
|
-
require "concurrent/atomics"
|
|
3
|
-
require "concurrent/executors"
|
|
4
|
-
require "thread"
|
|
5
|
-
|
|
6
|
-
module LaunchDarkly
|
|
7
|
-
# Simple wrapper for a FixedThreadPool that rejects new jobs if all the threads are busy, rather
|
|
8
|
-
# than blocking. Also provides a way to wait for all jobs to finish without shutting down.
|
|
9
|
-
# @private
|
|
10
|
-
class NonBlockingThreadPool
|
|
11
|
-
def initialize(capacity, name = 'LD/NonBlockingThreadPool')
|
|
12
|
-
@capacity = capacity
|
|
13
|
-
@pool = Concurrent::FixedThreadPool.new(capacity, name: name)
|
|
14
|
-
@semaphore = Concurrent::Semaphore.new(capacity)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Attempts to submit a job, but only if a worker is available. Unlike the regular post method,
|
|
18
|
-
# this returns a value: true if the job was submitted, false if all workers are busy.
|
|
19
|
-
def post
|
|
20
|
-
unless @semaphore.try_acquire(1)
|
|
21
|
-
return
|
|
22
|
-
end
|
|
23
|
-
@pool.post do
|
|
24
|
-
begin
|
|
25
|
-
yield
|
|
26
|
-
ensure
|
|
27
|
-
@semaphore.release(1)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Waits until no jobs are executing, without shutting down the pool.
|
|
33
|
-
def wait_all
|
|
34
|
-
@semaphore.acquire(@capacity)
|
|
35
|
-
@semaphore.release(@capacity)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def shutdown
|
|
39
|
-
@pool.shutdown
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def wait_for_termination
|
|
43
|
-
@pool.wait_for_termination
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
data/lib/ldclient-rb/polling.rb
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
require "ldclient-rb/impl/repeating_task"
|
|
2
|
-
|
|
3
|
-
require "concurrent/atomics"
|
|
4
|
-
require "json"
|
|
5
|
-
require "thread"
|
|
6
|
-
|
|
7
|
-
module LaunchDarkly
|
|
8
|
-
# @private
|
|
9
|
-
class PollingProcessor
|
|
10
|
-
def initialize(config, requestor)
|
|
11
|
-
@config = config
|
|
12
|
-
@requestor = requestor
|
|
13
|
-
@initialized = Concurrent::AtomicBoolean.new(false)
|
|
14
|
-
@started = Concurrent::AtomicBoolean.new(false)
|
|
15
|
-
@ready = Concurrent::Event.new
|
|
16
|
-
@task = Impl::RepeatingTask.new(@config.poll_interval, 0, -> { self.poll }, @config.logger, 'LD/PollingDataSource')
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def initialized?
|
|
20
|
-
@initialized.value
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def start
|
|
24
|
-
return @ready unless @started.make_true
|
|
25
|
-
@config.logger.info { "[LDClient] Initializing polling connection" }
|
|
26
|
-
@task.start
|
|
27
|
-
@ready
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def stop
|
|
31
|
-
stop_with_error_info
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def poll
|
|
35
|
-
begin
|
|
36
|
-
all_data = @requestor.request_all_data
|
|
37
|
-
if all_data
|
|
38
|
-
update_sink_or_data_store.init(all_data)
|
|
39
|
-
if @initialized.make_true
|
|
40
|
-
@config.logger.info { "[LDClient] Polling connection initialized" }
|
|
41
|
-
@ready.set
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
@config.data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::VALID, nil)
|
|
45
|
-
rescue JSON::ParserError => e
|
|
46
|
-
@config.logger.error { "[LDClient] JSON parsing failed for polling response." }
|
|
47
|
-
error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
|
|
48
|
-
LaunchDarkly::Interfaces::DataSource::ErrorInfo::INVALID_DATA,
|
|
49
|
-
0,
|
|
50
|
-
e.to_s,
|
|
51
|
-
Time.now
|
|
52
|
-
)
|
|
53
|
-
@config.data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED, error_info)
|
|
54
|
-
rescue UnexpectedResponseError => e
|
|
55
|
-
error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
|
|
56
|
-
LaunchDarkly::Interfaces::DataSource::ErrorInfo::ERROR_RESPONSE, e.status, nil, Time.now)
|
|
57
|
-
message = Util.http_error_message(e.status, "polling request", "will retry")
|
|
58
|
-
@config.logger.error { "[LDClient] #{message}" }
|
|
59
|
-
|
|
60
|
-
if Util.http_error_recoverable?(e.status)
|
|
61
|
-
@config.data_source_update_sink&.update_status(
|
|
62
|
-
LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
|
|
63
|
-
error_info
|
|
64
|
-
)
|
|
65
|
-
else
|
|
66
|
-
@ready.set # if client was waiting on us, make it stop waiting - has no effect if already set
|
|
67
|
-
stop_with_error_info error_info
|
|
68
|
-
end
|
|
69
|
-
rescue StandardError => e
|
|
70
|
-
Util.log_exception(@config.logger, "Exception while polling", e)
|
|
71
|
-
@config.data_source_update_sink&.update_status(
|
|
72
|
-
LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
|
|
73
|
-
LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(LaunchDarkly::Interfaces::DataSource::ErrorInfo::UNKNOWN, 0, e.to_s, Time.now)
|
|
74
|
-
)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
# The original implementation of this class relied on the feature store
|
|
80
|
-
# directly, which we are trying to move away from. Customers who might have
|
|
81
|
-
# instantiated this directly for some reason wouldn't know they have to set
|
|
82
|
-
# the config's sink manually, so we have to fall back to the store if the
|
|
83
|
-
# sink isn't present.
|
|
84
|
-
#
|
|
85
|
-
# The next major release should be able to simplify this structure and
|
|
86
|
-
# remove the need for fall back to the data store because the update sink
|
|
87
|
-
# should always be present.
|
|
88
|
-
#
|
|
89
|
-
private def update_sink_or_data_store
|
|
90
|
-
@config.data_source_update_sink || @config.feature_store
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
#
|
|
94
|
-
# @param [LaunchDarkly::Interfaces::DataSource::ErrorInfo, nil] error_info
|
|
95
|
-
#
|
|
96
|
-
private def stop_with_error_info(error_info = nil)
|
|
97
|
-
@task.stop
|
|
98
|
-
@config.logger.info { "[LDClient] Polling connection stopped" }
|
|
99
|
-
@config.data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::OFF, error_info)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
require "ldclient-rb/impl/model/serialization"
|
|
2
|
-
|
|
3
|
-
require "concurrent/atomics"
|
|
4
|
-
require "json"
|
|
5
|
-
require "uri"
|
|
6
|
-
require "http"
|
|
7
|
-
|
|
8
|
-
module LaunchDarkly
|
|
9
|
-
# @private
|
|
10
|
-
class UnexpectedResponseError < StandardError
|
|
11
|
-
def initialize(status)
|
|
12
|
-
@status = status
|
|
13
|
-
super("HTTP error #{status}")
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def status
|
|
17
|
-
@status
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# @private
|
|
22
|
-
class Requestor
|
|
23
|
-
CacheEntry = Struct.new(:etag, :body)
|
|
24
|
-
|
|
25
|
-
def initialize(sdk_key, config)
|
|
26
|
-
@sdk_key = sdk_key
|
|
27
|
-
@config = config
|
|
28
|
-
@http_client = LaunchDarkly::Util.new_http_client(config.base_uri, config)
|
|
29
|
-
.use(:auto_inflate)
|
|
30
|
-
.headers("Accept-Encoding" => "gzip")
|
|
31
|
-
@cache = @config.cache_store
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def request_all_data()
|
|
35
|
-
all_data = JSON.parse(make_request("/sdk/latest-all"), symbolize_names: true)
|
|
36
|
-
Impl::Model.make_all_store_data(all_data, @config.logger)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def stop
|
|
40
|
-
begin
|
|
41
|
-
@http_client.close
|
|
42
|
-
rescue
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def make_request(path)
|
|
49
|
-
uri = URI(
|
|
50
|
-
Util.add_payload_filter_key(@config.base_uri + path, @config)
|
|
51
|
-
)
|
|
52
|
-
headers = {}
|
|
53
|
-
Impl::Util.default_http_headers(@sdk_key, @config).each { |k, v| headers[k] = v }
|
|
54
|
-
headers["Connection"] = "keep-alive"
|
|
55
|
-
cached = @cache.read(uri)
|
|
56
|
-
unless cached.nil?
|
|
57
|
-
headers["If-None-Match"] = cached.etag
|
|
58
|
-
end
|
|
59
|
-
response = @http_client.request("GET", uri, {
|
|
60
|
-
headers: headers,
|
|
61
|
-
})
|
|
62
|
-
status = response.status.code
|
|
63
|
-
# must fully read body for persistent connections
|
|
64
|
-
body = response.to_s
|
|
65
|
-
@config.logger.debug { "[LDClient] Got response from uri: #{uri}\n\tstatus code: #{status}\n\theaders: #{response.headers.to_h}\n\tbody: #{body}" }
|
|
66
|
-
if status == 304 && !cached.nil?
|
|
67
|
-
body = cached.body
|
|
68
|
-
else
|
|
69
|
-
@cache.delete(uri)
|
|
70
|
-
if status < 200 || status >= 300
|
|
71
|
-
raise UnexpectedResponseError.new(status)
|
|
72
|
-
end
|
|
73
|
-
body = fix_encoding(body, response.headers["content-type"])
|
|
74
|
-
etag = response.headers["etag"]
|
|
75
|
-
@cache.write(uri, CacheEntry.new(etag, body)) unless etag.nil?
|
|
76
|
-
end
|
|
77
|
-
body
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def fix_encoding(body, content_type)
|
|
81
|
-
return body if content_type.nil?
|
|
82
|
-
media_type, charset = parse_content_type(content_type)
|
|
83
|
-
return body if charset.nil?
|
|
84
|
-
body.force_encoding(Encoding::find(charset)).encode(Encoding::UTF_8)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def parse_content_type(value)
|
|
88
|
-
return [nil, nil] if value.nil? || value == ''
|
|
89
|
-
parts = value.split(/; */)
|
|
90
|
-
return [value, nil] if parts.count < 2
|
|
91
|
-
charset = nil
|
|
92
|
-
parts.each do |part|
|
|
93
|
-
fields = part.split('=')
|
|
94
|
-
if fields.count >= 2 && fields[0] == 'charset'
|
|
95
|
-
charset = fields[1]
|
|
96
|
-
break
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
[parts[0], charset]
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
module LaunchDarkly
|
|
3
|
-
# A non-thread-safe implementation of a LRU cache set with only add and reset methods.
|
|
4
|
-
# Based on https://github.com/SamSaffron/lru_redux/blob/master/lib/lru_redux/cache.rb
|
|
5
|
-
# @private
|
|
6
|
-
class SimpleLRUCacheSet
|
|
7
|
-
def initialize(capacity)
|
|
8
|
-
@values = {}
|
|
9
|
-
@capacity = capacity
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# Adds a value to the cache or marks it recent if it was already there. Returns true if already there.
|
|
13
|
-
def add(value)
|
|
14
|
-
found = true
|
|
15
|
-
@values.delete(value) { found = false }
|
|
16
|
-
@values[value] = true
|
|
17
|
-
@values.shift if @values.length > @capacity
|
|
18
|
-
found
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def clear
|
|
22
|
-
@values = {}
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|