Skip to content

Commit

Permalink
[FFM-9925] - Testgrid - % rollout - Ruby SDK - Fix MM3 hash (#33)
Browse files Browse the repository at this point in the history
What
Various fixes to MM3 hash to bring it in alignment with GoLang SDK

    Fix input to MM3 hash to use <ATTR>:<VALUE> instead of <VALUE>:<ATTR>
    Set MM3 seed to 0
    Ignore 0 weighted distributions
    If bucket_by attribute is missing, fall back to identifier + log new SDK code
    Additional debug statements for easier diagnostics

Also

    Remove some IDE files that shouldn't be checked in
    Bump main version number
    Loosen Gem dependency requirements

Why
Review SDKs to make sure Murmur3 hash calculations are consistent across SDKs and buckets mappings align for customers that rely on this feature.

Testing
New percentage rollout tests added to testgrid, these will be committed later

---------

Co-authored-by: Erdi Rowlands <[email protected]>
  • Loading branch information
andybharness and erdirowlands authored Nov 15, 2023
1 parent 064024b commit 154cf41
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 74 deletions.
Empty file removed .idea/.gitignore
Empty file.
21 changes: 0 additions & 21 deletions .run/example.run.xml

This file was deleted.

33 changes: 0 additions & 33 deletions .run/sdk_test.rb.run.xml

This file was deleted.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [1.2.0] ** BREAKING **

- [FFM-9804] - The percentage rollout hash algorithm was slightly different compared to other Feature Flags SDKs, which resulted
in a different bucket allocation for the same target. While the overall percentage distribution was correct with the previous
algorithm; this fix ensures that the same target will get the same allocation per SDK. We are marking as a breaking change
as existing targets may get different allocations in a percentage rollout flag.

# [1.1.0]

- [FFM-7285] - Remove Metrics queue and implement Map for better memory usage
Expand Down
14 changes: 7 additions & 7 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ gem "minitest", "~> 5.0"
gem "standard", "~> 1.3"

# Caching support:
gem "rufus-scheduler"
gem "libcache"
gem "jwt"
gem "moneta"
gem "rufus-scheduler", "~> 3.8"
gem "libcache", "0.4.2"
gem "jwt", "~> 2.3"
gem "moneta", "~> 1.4"

# SSE support:
gem "rest-client"
gem "rest-client", "~> 2.1"

# Concurrency support:
gem "concurrent-ruby", "1.1.10", require: "concurrent"
gem "concurrent-ruby", "~> 1.1", require: "concurrent"

# Evaluator dependencies:
gem "murmurhash3"
gem "murmurhash3", "~> 0.1.6"

gem "typhoeus"

Expand Down
24 changes: 13 additions & 11 deletions lib/ff/ruby/server/sdk/api/evaluator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,24 @@ def find_variation(variations, identifier)
end

def get_normalized_number(property, bucket_by)

joined = property.to_s + ":" + bucket_by.to_s
hash = MurmurHash3::V32.str_hash(joined, joined.length)
joined = bucket_by.to_s + ":" + property.to_s
hash = MurmurHash3::V32.str_hash(joined, 0)
(hash % 100) + 1
end

def is_enabled(target, bucket_by, percentage)

property = get_attr_value(target, bucket_by)

if property != nil
if property == nil
old_bb = bucket_by
bucket_by = "identifier"
property = get_attr_value(target, bucket_by)
SdkCodes.warn_bucket_by_attr_not_found @logger, old_bb, property
end

if property != nil
bucket_id = get_normalized_number(property, bucket_by)

@logger.debug "MM3 percentage_check=%s bucket_by=%s value=%s bucket=%s" % [percentage, bucket_by, property, bucket_id]
return percentage > 0 && bucket_id <= percentage
end

Expand All @@ -206,13 +210,11 @@ def evaluate_distribution(distribution, target)
if distribution != nil

variation = nil

total_percentage = 0
distribution.variations.each do |weighted_variation|

variation = weighted_variation.variation

if is_enabled(target, distribution.bucket_by, weighted_variation.weight)

total_percentage = total_percentage + weighted_variation.weight
if is_enabled(target, distribution.bucket_by, total_percentage)
return variation
end
end
Expand Down
8 changes: 8 additions & 0 deletions lib/ff/ruby/server/sdk/common/sdk_codes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ def self.warn_default_variation_served(logger, identifier, target, default)
logger.warn SdkCodes.sdk_err_msg(6001, "identifier=%s, target=%s, default=%s" % [identifier, target.identifier, default])
end

def self.warn_bucket_by_attr_not_found(logger, attr_name, new_value)
if new_value == nil
new_value = "NOT FOUND"
end
logger.warn SdkCodes.sdk_err_msg(6002, "missing=%s, using value=%s" % [attr_name, new_value])
end

private

@map =
Expand All @@ -77,6 +84,7 @@ def self.warn_default_variation_served(logger, identifier, target, default)
# SDK_EVAL_6xxx
6000 => "Evaluated variation successfully",
6001 => "Default variation was served",
6002 => "BucketBy attribute not found in target attributes, falling back to 'identifier':",
# SDK_METRICS_7xxx
7000 => "Metrics thread started",
7001 => "Metrics thread exited",
Expand Down
2 changes: 1 addition & 1 deletion lib/ff/ruby/server/sdk/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Ruby
module Server
module Sdk

VERSION = "1.1.4"
VERSION = "1.2.0"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion scripts/sdk_specs.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash

export ff_ruby_sdk="ff-ruby-server-sdk"
export ff_ruby_sdk_version="1.1.4"
export ff_ruby_sdk_version="1.2.0"

0 comments on commit 154cf41

Please sign in to comment.