posthog-ruby 3.19.0 → 3.20.0
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/posthog/client.rb +22 -2
- data/lib/posthog/defaults.rb +1 -0
- data/lib/posthog/feature_flags.rb +29 -9
- data/lib/posthog/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36dffe9438cc269541f1642261b27b020bf05993eda1ad9999887428caa1667b
|
|
4
|
+
data.tar.gz: 9575ff454af5b89c0be1eb6abf4c7a1158fdbca88d4c708860339a1710b1393d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9badf7f03c2009d4c643b6e41f4ede382c0bf488eb0ae4d5cf33ec454110102e3fc342b5f3357b58b881f2a513628ba6056f0ccfa82d54ac8cafb4d814ae3811
|
|
7
|
+
data.tar.gz: e7918e45f9645da0052d65d205359e8384709f645f0f1b5201500a5cc97bb092aed771cd7fac7846f5bfc142fcb9e8168f55d9cbc750c6bbb8aab26e60e1138d
|
data/lib/posthog/client.rb
CHANGED
|
@@ -76,6 +76,13 @@ module PostHog
|
|
|
76
76
|
# @option opts [Integer] :feature_flag_request_max_retries How many times to retry a flag request after a
|
|
77
77
|
# transient network error. Each retry sleeps on the calling thread before retrying, so this adds to
|
|
78
78
|
# worst-case latency. Defaults to 1. Set to 0 to disable retrying.
|
|
79
|
+
# @option opts [Boolean] :feature_flags_async_load +true+ to fetch feature flag definitions for local
|
|
80
|
+
# evaluation only on the poller's background thread instead of the calling thread. The constructor
|
|
81
|
+
# returns without waiting for definitions: the poller fetches immediately on boot and, if that fails,
|
|
82
|
+
# keeps retrying on its regular polling interval until a load succeeds. Until then local evaluation
|
|
83
|
+
# treats definitions as absent (check {#feature_flags_loaded?}), so evaluations return nil with
|
|
84
|
+
# +only_evaluate_locally: true+, or fall back to the remote flags endpoint (which still runs on the
|
|
85
|
+
# calling thread) without it. Defaults to +false+.
|
|
79
86
|
# @option opts [Proc] :before_send A callback that receives the event hash and should return either a modified
|
|
80
87
|
# hash to be sent to PostHog or nil to prevent the event from being sent. e.g. `before_send: ->(event) { event }`.
|
|
81
88
|
# @option opts [Boolean] :disable_singleton_warning +true+ to suppress the warning when multiple clients share
|
|
@@ -162,7 +169,8 @@ module PostHog
|
|
|
162
169
|
opts[:feature_flag_request_timeout_seconds] || Defaults::FeatureFlags::FLAG_REQUEST_TIMEOUT_SECONDS,
|
|
163
170
|
opts[:on_error],
|
|
164
171
|
flag_definition_cache_provider: opts[:flag_definition_cache_provider],
|
|
165
|
-
feature_flag_request_max_retries: opts[:feature_flag_request_max_retries]
|
|
172
|
+
feature_flag_request_max_retries: opts[:feature_flag_request_max_retries],
|
|
173
|
+
async_load: opts[:feature_flags_async_load] == true
|
|
166
174
|
)
|
|
167
175
|
end
|
|
168
176
|
|
|
@@ -772,7 +780,8 @@ module PostHog
|
|
|
772
780
|
response
|
|
773
781
|
end
|
|
774
782
|
|
|
775
|
-
# Reload locally cached feature flag definitions
|
|
783
|
+
# Reload locally cached feature flag definitions synchronously on the
|
|
784
|
+
# calling thread.
|
|
776
785
|
#
|
|
777
786
|
# @return [void]
|
|
778
787
|
def reload_feature_flags
|
|
@@ -787,6 +796,17 @@ module PostHog
|
|
|
787
796
|
@feature_flags_poller.load_feature_flags(true)
|
|
788
797
|
end
|
|
789
798
|
|
|
799
|
+
# Whether feature flag definitions for local evaluation are currently loaded.
|
|
800
|
+
# False until the first successful load, and false again if a quota-limited
|
|
801
|
+
# (402) response discards the definitions.
|
|
802
|
+
#
|
|
803
|
+
# @return [Boolean]
|
|
804
|
+
def feature_flags_loaded?
|
|
805
|
+
return false if @disabled
|
|
806
|
+
|
|
807
|
+
@feature_flags_poller.definitions_loaded?
|
|
808
|
+
end
|
|
809
|
+
|
|
790
810
|
# Whether the client will actually send events. It is disabled when the
|
|
791
811
|
# api_key is missing or blank, in which case every capture call no-ops.
|
|
792
812
|
#
|
data/lib/posthog/defaults.rb
CHANGED
|
@@ -19,6 +19,7 @@ module PostHog
|
|
|
19
19
|
|
|
20
20
|
module FeatureFlags
|
|
21
21
|
FLAG_REQUEST_TIMEOUT_SECONDS = 3
|
|
22
|
+
POLLING_INTERVAL_SECONDS = 30
|
|
22
23
|
# Number of retries for a flag request after a transient network error.
|
|
23
24
|
# Flag requests are stateless and cause no server-side mutation, so
|
|
24
25
|
# retrying is safe.
|
|
@@ -30,6 +30,7 @@ module PostHog
|
|
|
30
30
|
include PostHog::Utils
|
|
31
31
|
|
|
32
32
|
# @param polling_interval [Integer, nil] Seconds between local feature flag definition polls.
|
|
33
|
+
# Defaults to {Defaults::FeatureFlags::POLLING_INTERVAL_SECONDS}.
|
|
33
34
|
# @param secret_key [String, nil] Credential used to fetch local evaluation definitions. Accepts either a
|
|
34
35
|
# Personal API Key (`phx_...`) or a Project Secret API Key (`phs_...`).
|
|
35
36
|
# @param project_api_key [String] Project API key.
|
|
@@ -40,6 +41,9 @@ module PostHog
|
|
|
40
41
|
# @param feature_flag_request_max_retries [Integer, nil] Retries after a transient network error or retryable
|
|
41
42
|
# HTTP response status on a flag request. Defaults to {Defaults::FeatureFlags::FLAG_REQUEST_MAX_RETRIES}.
|
|
42
43
|
# Set to 0 to disable retrying.
|
|
44
|
+
# @param async_load [Boolean] When true, flag definitions are fetched only on the poller thread: an
|
|
45
|
+
# immediate first tick at construction, then the regular polling cadence, which keeps retrying until a
|
|
46
|
+
# load succeeds.
|
|
43
47
|
def initialize(
|
|
44
48
|
polling_interval,
|
|
45
49
|
secret_key,
|
|
@@ -48,9 +52,10 @@ module PostHog
|
|
|
48
52
|
feature_flag_request_timeout_seconds,
|
|
49
53
|
on_error = nil,
|
|
50
54
|
flag_definition_cache_provider: nil,
|
|
51
|
-
feature_flag_request_max_retries: nil
|
|
55
|
+
feature_flag_request_max_retries: nil,
|
|
56
|
+
async_load: false
|
|
52
57
|
)
|
|
53
|
-
@polling_interval = polling_interval ||
|
|
58
|
+
@polling_interval = polling_interval || Defaults::FeatureFlags::POLLING_INTERVAL_SECONDS
|
|
54
59
|
@secret_key = secret_key
|
|
55
60
|
@project_api_key = project_api_key
|
|
56
61
|
@host = host
|
|
@@ -65,14 +70,16 @@ module PostHog
|
|
|
65
70
|
@on_error = on_error || proc { |status, error| }
|
|
66
71
|
@quota_limited = Concurrent::AtomicBoolean.new(false)
|
|
67
72
|
@flags_etag = Concurrent::AtomicReference.new(nil)
|
|
68
|
-
@flag_definitions_loaded_at = nil
|
|
73
|
+
@flag_definitions_loaded_at = Concurrent::AtomicReference.new(nil)
|
|
74
|
+
@async_load = async_load
|
|
69
75
|
|
|
70
76
|
@flag_definition_cache_provider = flag_definition_cache_provider
|
|
71
77
|
FlagDefinitionCacheProvider.validate!(@flag_definition_cache_provider) if @flag_definition_cache_provider
|
|
72
78
|
|
|
73
79
|
@task =
|
|
74
80
|
Concurrent::TimerTask.new(
|
|
75
|
-
execution_interval: polling_interval
|
|
81
|
+
execution_interval: @polling_interval,
|
|
82
|
+
run_now: @async_load
|
|
76
83
|
) { _load_feature_flags }
|
|
77
84
|
|
|
78
85
|
# If no secret_key, disable local evaluation & thus polling for definitions
|
|
@@ -80,19 +87,31 @@ module PostHog
|
|
|
80
87
|
logger.info 'No secret_key provided, disabling local evaluation'
|
|
81
88
|
@loaded_flags_successfully_once.make_true
|
|
82
89
|
else
|
|
83
|
-
# load once before timer
|
|
84
|
-
load_feature_flags
|
|
90
|
+
# load once synchronously before timer, unless @async_load
|
|
91
|
+
load_feature_flags unless @async_load
|
|
85
92
|
@task.execute
|
|
86
93
|
end
|
|
87
94
|
end
|
|
88
95
|
|
|
89
96
|
def load_feature_flags(force_reload = false)
|
|
90
|
-
return
|
|
97
|
+
return if (@loaded_flags_successfully_once.true? || @async_load) && !force_reload
|
|
91
98
|
|
|
92
99
|
_load_feature_flags
|
|
93
100
|
end
|
|
94
101
|
|
|
95
|
-
|
|
102
|
+
# Whether flag definitions are currently loaded. False until the first
|
|
103
|
+
# successful load, and false again if a quota-limited (402) response
|
|
104
|
+
# discards them.
|
|
105
|
+
def definitions_loaded?
|
|
106
|
+
!@flag_definitions_loaded_at.value.nil?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Epoch milliseconds of the last successful definitions load, or nil.
|
|
110
|
+
def flag_definitions_loaded_at
|
|
111
|
+
@flag_definitions_loaded_at.value
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
attr_reader :feature_flags_by_key
|
|
96
115
|
|
|
97
116
|
def get_feature_variants(
|
|
98
117
|
distinct_id,
|
|
@@ -1183,6 +1202,7 @@ module PostHog
|
|
|
1183
1202
|
@feature_flags_by_key = {}
|
|
1184
1203
|
@group_type_mapping = Concurrent::Hash.new
|
|
1185
1204
|
@cohorts = Concurrent::Hash.new
|
|
1205
|
+
@flag_definitions_loaded_at.value = nil
|
|
1186
1206
|
@loaded_flags_successfully_once.make_false
|
|
1187
1207
|
@quota_limited.make_true
|
|
1188
1208
|
return
|
|
@@ -1231,7 +1251,7 @@ module PostHog
|
|
|
1231
1251
|
@cohorts = Concurrent::Hash[deep_symbolize_keys(cohorts)]
|
|
1232
1252
|
|
|
1233
1253
|
logger.debug "Loaded #{@feature_flags.length} feature flags and #{@cohorts.length} cohorts"
|
|
1234
|
-
@flag_definitions_loaded_at = (Time.now.to_f * 1000).to_i
|
|
1254
|
+
@flag_definitions_loaded_at.value = (Time.now.to_f * 1000).to_i
|
|
1235
1255
|
@loaded_flags_successfully_once.make_true if @loaded_flags_successfully_once.false?
|
|
1236
1256
|
end
|
|
1237
1257
|
|
data/lib/posthog/version.rb
CHANGED