posthog-ruby 3.26.4 → 3.27.1

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: f8ce806f1bb00b10162307764e024a4019e9ea6d924700da5443ad15f430b4c8
4
- data.tar.gz: b810a1652c8615a544fc24082b8e99a34ddf3db96c1605e29e8fc36ff2ae3cc3
3
+ metadata.gz: 125a7a9c4063477324ed9654c1035ff28e959cb6c389dfbcfc5ee08bb17153ab
4
+ data.tar.gz: b02e50631f58cb0e119184c1556766c55ee0e1ae578514620b6217a916207b7e
5
5
  SHA512:
6
- metadata.gz: 9b58080118c7780408d1f7e7992ef99d1e4a76db837babc8057e09b826a4ef0b2bd4a5a369cbb164fe8675735cd9074a4d9b312f4532198c2415782a3c8cf820
7
- data.tar.gz: 70ea5da7b0cc56c9a96681cc64611e85b931deb63359c64f99507d9bb292b459f1d5c246ba13a8961b28af15e6009fc7338ea6a04f02af74120c05e8e56a65c1
6
+ metadata.gz: 1adee637ab5766731429e73e4bd41b102c9bb33fc285b75b4a62dd173a6fa0c4825ee47ff87b007d8cc8c517c8eab6103b33337b62fd4504497c2c127580c7c2
7
+ data.tar.gz: 82c8accf93eede6fe7c4748967377b7fa9a1ffc28f7c9ed85e6355ba81d2312962767488436af285c57e0bfc9ebcd442dd486157644b708e9dbd03ad045fd712
@@ -85,9 +85,9 @@ module PostHog
85
85
 
86
86
  # @param opts [Hash] Client configuration.
87
87
  # @option opts [String, nil] :api_key Your project's API key. Missing or blank values disable the client.
88
- # @option opts [String, nil] :secret_key The credential used for local feature flag evaluation and remote
89
- # config. Accepts either a Personal API Key (`phx_...`) or a Project Secret API Key (`phs_...`). Required
90
- # for local feature flag evaluation.
88
+ # @option opts [String, nil] :secret_key The credential used to fetch local feature flag definitions and remote
89
+ # config. Accepts either a Personal API Key (`phx_...`) or a Project Secret API Key (`phs_...`). Not required
90
+ # for local evaluation when definitions are read from +:flag_definition_cache_provider+.
91
91
  # @option opts [String, nil] :personal_api_key
92
92
  # @deprecated Use +:secret_key+ instead. Retained as an alias; when both are supplied, +:secret_key+ wins.
93
93
  # @option opts [String] :host Fully qualified hostname of the PostHog server. Defaults to `https://us.i.posthog.com`.
@@ -180,6 +180,7 @@ module PostHog
180
180
  @feature_flags_poller = nil
181
181
  @secret_key = secret_key
182
182
  @personal_api_key = secret_key
183
+ @flag_definition_cache_provider = opts[:flag_definition_cache_provider]
183
184
 
184
185
  if @disabled && !opts[:silence_disabled_client_error]
185
186
  logger.error('api_key is missing or empty after trimming whitespace; check your project API key')
@@ -214,7 +215,7 @@ module PostHog
214
215
  opts[:host],
215
216
  opts[:feature_flag_request_timeout_seconds] || Defaults::FeatureFlags::FLAG_REQUEST_TIMEOUT_SECONDS,
216
217
  opts[:on_error],
217
- flag_definition_cache_provider: opts[:flag_definition_cache_provider],
218
+ flag_definition_cache_provider: @flag_definition_cache_provider,
218
219
  feature_flag_request_max_retries: opts[:feature_flag_request_max_retries],
219
220
  async_load: opts[:feature_flags_async_load] == true,
220
221
  user_agent: @headers['User-Agent'],
@@ -883,9 +884,9 @@ module PostHog
883
884
  def reload_feature_flags
884
885
  return if @disabled
885
886
 
886
- unless @secret_key
887
+ unless @secret_key || @flag_definition_cache_provider
887
888
  logger.error(
888
- 'You need to specify a secret_key to locally evaluate feature flags'
889
+ 'You need to specify a secret_key or flag_definition_cache_provider to locally evaluate feature flags'
889
890
  )
890
891
  return
891
892
  end
@@ -81,11 +81,20 @@ module PostHog
81
81
  end
82
82
 
83
83
  # @param key [String, Symbol] The feature flag key.
84
- # @return [Boolean] true when the flag is enabled, false when disabled or missing.
85
- def enabled?(key)
84
+ # @param default_value [Boolean, nil] Returned when the flag has no value in this
85
+ # snapshot — it was never loaded, the `/flags` request failed, or no flag with that
86
+ # key exists. A flag that does have a value, including `false` and variant strings,
87
+ # always wins over this default; so does a flag the server returned but marked as
88
+ # failed, which resolves to `false`. Defaults to `nil`, which keeps the historical
89
+ # `false` result for a missing flag.
90
+ # @return [Boolean] true when the flag is enabled, false when disabled, and the
91
+ # caller-supplied default (or false when none was supplied) when the flag is missing.
92
+ def enabled?(key, default_value: nil)
86
93
  key = key.to_s
87
94
  flag = @flags[key]
88
95
  _record_access(key, flag)
96
+ return !!default_value if flag.nil? && !default_value.nil?
97
+
89
98
  flag&.enabled ? true : false
90
99
  end
91
100
 
@@ -100,9 +100,9 @@ module PostHog
100
100
  run_now: @async_load
101
101
  ) { _load_feature_flags }
102
102
 
103
- # If no secret_key, disable local evaluation & thus polling for definitions
104
- if @secret_key.nil?
105
- logger.info 'No secret_key provided, disabling local evaluation'
103
+ # Local evaluation can load definitions from either the API or an external cache.
104
+ if @secret_key.nil? && @flag_definition_cache_provider.nil?
105
+ logger.info 'No secret_key or flag_definition_cache_provider provided, disabling local evaluation'
106
106
  @loaded_flags_successfully_once.make_true
107
107
  else
108
108
  # load once synchronously before timer, unless @async_load
@@ -1260,7 +1260,8 @@ module PostHog
1260
1260
 
1261
1261
  if @flag_definition_cache_provider
1262
1262
  begin
1263
- should_fetch = @flag_definition_cache_provider.should_fetch_flag_definitions?
1263
+ # Cache-only readers must not acquire or renew fetch leadership.
1264
+ should_fetch = @secret_key && @flag_definition_cache_provider.should_fetch_flag_definitions?
1264
1265
  rescue StandardError => e
1265
1266
  logger.error("[FEATURE FLAGS] Cache provider should_fetch error: #{e}")
1266
1267
  should_fetch = true
@@ -1271,6 +1272,10 @@ module PostHog
1271
1272
  begin
1272
1273
  cached_data = @flag_definition_cache_provider.flag_definitions
1273
1274
  if cached_data
1275
+ unless cached_data.is_a?(Hash) && get_by_symbol_or_string_key(cached_data, 'flags').is_a?(Array)
1276
+ raise ArgumentError, 'Cached flag definitions must contain a flags array'
1277
+ end
1278
+
1274
1279
  logger.debug '[FEATURE FLAGS] Using cached flag definitions from external cache'
1275
1280
  _apply_flag_definitions(cached_data)
1276
1281
  return
@@ -1288,6 +1293,11 @@ module PostHog
1288
1293
  end
1289
1294
 
1290
1295
  def _fetch_and_apply_flag_definitions
1296
+ unless @secret_key
1297
+ logger.warn '[FEATURE FLAGS] A secret_key is required to fetch flag definitions from PostHog'
1298
+ return
1299
+ end
1300
+
1291
1301
  begin
1292
1302
  res = _request_feature_flag_definitions(etag: @flags_etag.value)
1293
1303
  rescue StandardError => e
@@ -5,7 +5,8 @@ module PostHog
5
5
  #
6
6
  # Enables multi-worker environments (Kubernetes, load-balanced servers,
7
7
  # serverless functions) to share flag definitions via an external cache,
8
- # reducing redundant API calls.
8
+ # reducing redundant API calls. Cache consumers need only the project API key;
9
+ # +:secret_key+ is required only for workers that fetch definitions from PostHog.
9
10
  #
10
11
  # Implement the four required methods on any object and pass it as the
11
12
  # +:flag_definition_cache_provider+ option when creating a {Client}.
@@ -16,7 +17,7 @@ module PostHog
16
17
  # Retrieve cached flag definitions. Return a Hash with +:flags+,
17
18
  # +:group_type_mapping+, +:cohorts+, +:minimal_flag_called_events+, and +:property_matching_version+
18
19
  # keys, or +nil+ if the cache is empty. Returning +nil+ triggers an API
19
- # fetch when no flags are loaded yet (emergency fallback). Providers
20
+ # fetch when no flags are loaded yet and +:secret_key+ is configured (emergency fallback). Providers
20
21
  # written before +:minimal_flag_called_events+ existed continue to work;
21
22
  # a missing key is treated as +false+. Preserve +:property_matching_version+
22
23
  # with the definitions: exactly +2+ selects explicit equality; missing/1
@@ -27,7 +28,9 @@ module PostHog
27
28
  # @!method should_fetch_flag_definitions?
28
29
  # Return +true+ if this instance should fetch new definitions from the
29
30
  # API, +false+ to read from cache instead. Use for distributed lock
30
- # coordination so only one worker fetches at a time.
31
+ # coordination so only one worker fetches at a time. Called only when
32
+ # +:secret_key+ is configured. Without it, the SDK reads +flag_definitions+
33
+ # directly without acquiring or renewing fetch leadership.
31
34
  # @return [Boolean]
32
35
  #
33
36
  # @!method on_flag_definitions_received(data)
@@ -53,12 +56,16 @@ module PostHog
53
56
  # - +on_flag_definitions_received+ errors are logged; flags remain in memory
54
57
  # - +shutdown+ errors are logged; shutdown continues
55
58
  #
59
+ # API fallback requires +:secret_key+. Without it, the SDK logs a warning and
60
+ # keeps any previously loaded definitions. Cache-only readers skip the fetch
61
+ # decision and never publish. Polling and manual reloads continue reading the
62
+ # cache so consumers can pick up later updates.
63
+ #
56
64
  # == Example
57
65
  #
58
66
  # cache = RedisFlagCache.new(redis, service_key: 'my-service')
59
67
  # client = PostHog::Client.new(
60
68
  # api_key: '<project_api_key>',
61
- # secret_key: '<secret_key>',
62
69
  # flag_definition_cache_provider: cache
63
70
  # )
64
71
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PostHog
4
- VERSION = '3.26.4'
4
+ VERSION = '3.27.1'
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.26.4
4
+ version: 3.27.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''