posthog-ruby 3.27.1 → 3.28.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 125a7a9c4063477324ed9654c1035ff28e959cb6c389dfbcfc5ee08bb17153ab
4
- data.tar.gz: b02e50631f58cb0e119184c1556766c55ee0e1ae578514620b6217a916207b7e
3
+ metadata.gz: 561f4ebad1a6cd75904b800f540c0dbb9352cc081dc57bf5cc0a5dcb82925e89
4
+ data.tar.gz: 5e9ce62f5e48c5380ce71e454507bafa6825a8e7e6db6c05b8896b8c5a665c62
5
5
  SHA512:
6
- metadata.gz: 1adee637ab5766731429e73e4bd41b102c9bb33fc285b75b4a62dd173a6fa0c4825ee47ff87b007d8cc8c517c8eab6103b33337b62fd4504497c2c127580c7c2
7
- data.tar.gz: 82c8accf93eede6fe7c4748967377b7fa9a1ffc28f7c9ed85e6355ba81d2312962767488436af285c57e0bfc9ebcd442dd486157644b708e9dbd03ad045fd712
6
+ metadata.gz: 41f3fde35a6e73ffa54b09fff2d88990057a3fac677153b2e14e6547fb20dbacebcc7a687bae432a98c62cabad572b5dc64cc57fb0cfbab554d7c72581d84ab8
7
+ data.tar.gz: e596b42169af511879c3397bc6e42aa2410bee4aa4d519b6958ad87d0800da67e6b208670abd809f4bd34d52616db2fd9a1d1ae3b3b8ebdf4c867edfb5ad186f
@@ -1110,6 +1110,13 @@ module PostHog
1110
1110
  groups: {}, group_properties: {}, snapshot: _evaluation_snapshot)
1111
1111
  flag_filters = flag[:filters] || {}
1112
1112
 
1113
+ # Holdouts precede release conditions: a held-out identifier is excluded from
1114
+ # the flag's targeting entirely rather than bucketed into one of its variants.
1115
+ # The per-condition aggregation handled below never changes holdout membership,
1116
+ # so this uses the flag-level bucketing identity the caller resolved.
1117
+ holdout_variant = holdout_variant_for(flag_filters[:holdout], distinct_id)
1118
+ return holdout_variant unless holdout_variant.nil?
1119
+
1113
1120
  flag_conditions = flag_filters[:groups] || []
1114
1121
  flag_aggregation = flag_filters[:aggregation_group_type_index]
1115
1122
  early_exit = flag_filters[:early_exit] == true
@@ -1233,6 +1240,36 @@ module PostHog
1233
1240
  (Integer(hash_key[0..14], 16).to_f / 0xfffffffffffffff)
1234
1241
  end
1235
1242
 
1243
+ # An experiment holdout excludes an identifier from the flag's release conditions
1244
+ # entirely, resolving it to the synthetic variant "holdout-<id>". That variant does
1245
+ # not need to exist in `filters.multivariate.variants`. Returns nil when the flag has
1246
+ # no usable holdout or the identifier falls outside it, leaving ordinary evaluation
1247
+ # unchanged.
1248
+ def holdout_variant_for(holdout, bucketing_value)
1249
+ return nil unless holdout.is_a?(Hash)
1250
+
1251
+ id = holdout[:id]
1252
+ exclusion_percentage = holdout[:exclusion_percentage]
1253
+ return nil if id.nil? || !exclusion_percentage.is_a?(Numeric)
1254
+
1255
+ # The server clamps an out-of-range percentage rather than rejecting it, and treats
1256
+ # 100 as everyone without hashing, so a full holdout can't miss on a hash boundary.
1257
+ # Fractional percentages are kept as-is.
1258
+ percentage = exclusion_percentage.to_f.clamp(0, 100)
1259
+ return nil if percentage < 100 && _holdout_hash(bucketing_value) > (percentage / 100)
1260
+
1261
+ "holdout-#{id}"
1262
+ end
1263
+
1264
+ # Holdout membership hashes `holdout-<bucketing value>` with no separator, salt, flag
1265
+ # key or holdout id taking part, so one identity lands in the same holdout population
1266
+ # on every flag, the way the server buckets it. The dot-separated flag hash above
1267
+ # selects a different population and must not be reused here.
1268
+ def _holdout_hash(bucketing_value)
1269
+ hash_key = Digest::SHA1.hexdigest "holdout-#{bucketing_value}"
1270
+ (Integer(hash_key[0..14], 16).to_f / 0xfffffffffffffff)
1271
+ end
1272
+
1236
1273
  def get_matching_variant(flag, distinct_id)
1237
1274
  hash_value = _hash(flag[:key], distinct_id, 'variant')
1238
1275
  matching_variant = variant_lookup_table(flag).find do |variant|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PostHog
4
- VERSION = '3.27.1'
4
+ VERSION = '3.28.0'
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.27.1
4
+ version: 3.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''