posthog-ruby 3.23.6 → 3.23.7

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: 48bec2a9194efaee9e0b2dee9c7ca1c3af4697a8b85b8256b34302cd9ab91818
4
- data.tar.gz: f5c4ae56806620e636e1d65fd20f18baed769b1f2e8fec9154c4cbb1515ebb80
3
+ metadata.gz: 67be906751ad3545830e00ac558a3787ba935d08c5414b216b653b63a745a424
4
+ data.tar.gz: 589fa3335b009dc16e22224e4708d55079e9b236c5c6cdfdba6f996fdb191af3
5
5
  SHA512:
6
- metadata.gz: 1aaf63d6764d231e7f461650651e419abebeaf26cb151ef168497c4ac0d8ce3ced14ef1e23a3308f14126f57aa78f337e2b9b3064983713d92dfea26cd7ffffa
7
- data.tar.gz: 3b851e37e73b2cb8e1dfe8439da24c45e341ca3adf5f1bfe89318e6f9a8270e7ee070216df644320ca16bc9236aa1f9e1b28d73f0968d63ca38ad80cc8dfe1c0
6
+ metadata.gz: 1d7c92afb919cfb24e8e3a9bcfd3605cb4fce07d784019f1dd80fd0c685bc4ddde18d5b0322091fe49ad0e474cedbcae3804baf624697be650eed0418a450cdd
7
+ data.tar.gz: c9bec9d494e68a63b594c6960dc5e9d30d32d918c68df1a7dd83ba3a047179ff87bf5756f5dd0434ffde305b14a392457cbac7762c84e8ea91ed9839fab09763
@@ -191,6 +191,12 @@ module PostHog
191
191
  end
192
192
  end
193
193
 
194
+ # Initialize tracking before the poller can load definitions (including async loads).
195
+ @distinct_id_has_sent_flag_calls_mutex = Mutex.new
196
+ @distinct_id_has_sent_flag_calls = SizeLimitedHash.new(Defaults::MAX_HASH_SIZE) do |hash, key|
197
+ hash[key] = SizeLimitedArray.new(Defaults::MAX_HASH_SIZE)
198
+ end
199
+
194
200
  unless @disabled
195
201
  @feature_flags_poller =
196
202
  FeatureFlagsPoller.new(
@@ -203,15 +209,12 @@ module PostHog
203
209
  flag_definition_cache_provider: opts[:flag_definition_cache_provider],
204
210
  feature_flag_request_max_retries: opts[:feature_flag_request_max_retries],
205
211
  async_load: opts[:feature_flags_async_load] == true,
206
- user_agent: @headers['User-Agent']
212
+ user_agent: @headers['User-Agent'],
213
+ flag_definitions_update_mutex: @distinct_id_has_sent_flag_calls_mutex,
214
+ on_flag_definitions_updated: -> { @distinct_id_has_sent_flag_calls.clear }
207
215
  )
208
216
  end
209
217
 
210
- @distinct_id_has_sent_flag_calls_mutex = Mutex.new
211
- @distinct_id_has_sent_flag_calls = SizeLimitedHash.new(Defaults::MAX_HASH_SIZE) do |hash, key|
212
- hash[key] = SizeLimitedArray.new(Defaults::MAX_HASH_SIZE)
213
- end
214
-
215
218
  @before_send = opts[:before_send]
216
219
  @is_server = opts.fetch(:is_server, true) != false
217
220
  @deprecation_emitted_for = Concurrent::Set.new
@@ -45,6 +45,9 @@ module PostHog
45
45
  # immediate first tick at construction, then the regular polling cadence, which keeps retrying until a
46
46
  # load succeeds.
47
47
  # @param user_agent [String] User-Agent header sent with feature flag requests.
48
+ # @param flag_definitions_update_mutex [Mutex] Internal lock shared with flag-called deduplication.
49
+ # @param on_flag_definitions_updated [Proc, nil] Internal callback after definitions are applied or discarded,
50
+ # called while holding flag_definitions_update_mutex.
48
51
  def initialize(
49
52
  polling_interval,
50
53
  secret_key,
@@ -55,7 +58,9 @@ module PostHog
55
58
  flag_definition_cache_provider: nil,
56
59
  feature_flag_request_max_retries: nil,
57
60
  async_load: false,
58
- user_agent: "posthog-ruby/#{PostHog::VERSION}"
61
+ user_agent: "posthog-ruby/#{PostHog::VERSION}",
62
+ on_flag_definitions_updated: nil,
63
+ flag_definitions_update_mutex: Mutex.new
59
64
  )
60
65
  @polling_interval = polling_interval || Defaults::FeatureFlags::POLLING_INTERVAL_SECONDS
61
66
  @secret_key = secret_key
@@ -75,6 +80,8 @@ module PostHog
75
80
  @flag_definitions_loaded_at = Concurrent::AtomicReference.new(nil)
76
81
  @async_load = async_load
77
82
  @user_agent = user_agent
83
+ @on_flag_definitions_updated = on_flag_definitions_updated
84
+ @flag_definitions_update_mutex = flag_definitions_update_mutex
78
85
  # Server-controlled gate for minimal `$feature_flag_called` events, read
79
86
  # from the top-level `minimal_flag_called_events` key of the local
80
87
  # evaluation definitions payload. false when the server does not send it.
@@ -1221,14 +1228,18 @@ module PostHog
1221
1228
  '[FEATURE FLAGS] Feature flags quota limit exceeded - unsetting all local flags. ' \
1222
1229
  'Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts'
1223
1230
  )
1224
- @feature_flags = Concurrent::Array.new
1225
- @feature_flags_by_key = {}
1226
- @group_type_mapping = Concurrent::Hash.new
1227
- @cohorts = Concurrent::Hash.new
1228
- @flag_definitions_loaded_at.value = nil
1229
- @minimal_flag_called_events = false
1230
- @loaded_flags_successfully_once.make_false
1231
- @quota_limited.make_true
1231
+ @flag_definitions_update_mutex.synchronize do
1232
+ definitions_were_loaded = definitions_loaded?
1233
+ @feature_flags = Concurrent::Array.new
1234
+ @feature_flags_by_key = {}
1235
+ @group_type_mapping = Concurrent::Hash.new
1236
+ @cohorts = Concurrent::Hash.new
1237
+ @flag_definitions_loaded_at.value = nil
1238
+ @minimal_flag_called_events = false
1239
+ @loaded_flags_successfully_once.make_false
1240
+ @quota_limited.make_true
1241
+ @on_flag_definitions_updated&.call if definitions_were_loaded
1242
+ end
1232
1243
  return
1233
1244
  end
1234
1245
 
@@ -1265,21 +1276,26 @@ module PostHog
1265
1276
  cohorts = get_by_symbol_or_string_key(data, 'cohorts') || {}
1266
1277
  minimal_flag_called_events = get_by_symbol_or_string_key(data, 'minimal_flag_called_events')
1267
1278
 
1268
- @feature_flags = Concurrent::Array.new(flags.map { |f| deep_symbolize_keys(f) })
1269
-
1279
+ new_flags = Concurrent::Array.new(flags.map { |f| deep_symbolize_keys(f) })
1270
1280
  new_by_key = {}
1271
- @feature_flags.each do |flag|
1281
+ new_flags.each do |flag|
1272
1282
  new_by_key[flag[:key]] = flag unless flag[:key].nil?
1273
1283
  end
1274
- @feature_flags_by_key = new_by_key
1275
-
1276
- @group_type_mapping = Concurrent::Hash[deep_symbolize_keys(group_type_mapping)]
1277
- @cohorts = Concurrent::Hash[deep_symbolize_keys(cohorts)]
1278
- @minimal_flag_called_events = minimal_flag_called_events == true
1279
-
1280
- logger.debug "Loaded #{@feature_flags.length} feature flags and #{@cohorts.length} cohorts"
1281
- @flag_definitions_loaded_at.value = (Time.now.to_f * 1000).to_i
1282
- @loaded_flags_successfully_once.make_true if @loaded_flags_successfully_once.false?
1284
+ new_group_type_mapping = Concurrent::Hash[deep_symbolize_keys(group_type_mapping)]
1285
+ new_cohorts = Concurrent::Hash[deep_symbolize_keys(cohorts)]
1286
+
1287
+ # A read of the new definitions must not record its event before the tracker reset.
1288
+ @flag_definitions_update_mutex.synchronize do
1289
+ @feature_flags = new_flags
1290
+ @feature_flags_by_key = new_by_key
1291
+ @group_type_mapping = new_group_type_mapping
1292
+ @cohorts = new_cohorts
1293
+ @minimal_flag_called_events = minimal_flag_called_events == true
1294
+ @flag_definitions_loaded_at.value = (Time.now.to_f * 1000).to_i
1295
+ @loaded_flags_successfully_once.make_true if @loaded_flags_successfully_once.false?
1296
+ @on_flag_definitions_updated&.call
1297
+ end
1298
+ logger.debug "Loaded #{new_flags.length} feature flags and #{new_cohorts.length} cohorts"
1283
1299
  end
1284
1300
 
1285
1301
  def _request_feature_flag_definitions(etag: nil)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PostHog
4
- VERSION = '3.23.6'
4
+ VERSION = '3.23.7'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: posthog-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.23.6
4
+ version: 3.23.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''