Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test-harness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ jobs:
with:
sdks-to-test: ruby
sdk-github-sha: ${{github.event.pull_request.head.sha}}
sdk-capabilities: '{ "Ruby": ["clientCustomData", "v2Config", "variableFeatureId", "allVariables", "allFeatures", "evalReason", "cloudEvalReason", "eventsEvalReason", "variablesFeatureId"]}'
1 change: 1 addition & 0 deletions lib/devcycle-ruby-server-sdk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
require 'devcycle-ruby-server-sdk/eval_hooks_runner'
require 'devcycle-ruby-server-sdk/models/eval_hook'
require 'devcycle-ruby-server-sdk/models/eval_hook_context'
require 'devcycle-ruby-server-sdk/eval_reasons'

# APIs
require 'devcycle-ruby-server-sdk/api/client'
Expand Down
20 changes: 18 additions & 2 deletions lib/devcycle-ruby-server-sdk/api/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -195,16 +195,19 @@ def variable(user, key, default, opts = {})
value = default
type = determine_variable_type(default)
defaulted = true
eval = { reason: DevCycle::DEFAULT_REASONS::USER_NOT_TARGETED, details: DevCycle::DEFAULT_REASON_DETAILS::USER_NOT_TARGETED }
if local_bucketing_initialized? && @local_bucketing.has_config
type_code = variable_type_code_from_type(type)
variable_pb = variable_for_user_pb(user, key, type_code)
unless variable_pb.nil?
value = get_variable_value(variable_pb)
defaulted = false
end
eval = get_eval_reason(variable_pb)
else
eval = { reason: DevCycle::DEFAULT_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::MISSING_CONFIG }
@logger.warn("Local bucketing not initialized, returning default value for variable #{key}")
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_defaulted], target: key })
variable_event = Event.new({ type: DevCycle::EventTypes[:agg_variable_defaulted], target: key, metaData: { evalReason: DevCycle::DEFAULT_REASONS::DEFAULT }})
bucketed_config = BucketedUserConfig.new({}, {}, {}, {}, {}, {}, [])
@event_queue.queue_aggregate_event(variable_event, bucketed_config)
end
Expand All @@ -214,7 +217,8 @@ def variable(user, key, default, opts = {})
value: value,
type: type,
defaultValue: default,
isDefaulted: defaulted
isDefaulted: defaulted,
eval: eval
})
end

Expand Down Expand Up @@ -574,6 +578,18 @@ def get_variable_value(variable_pb)
end
end

def get_eval_reason(variable_pb)
if variable_pb.nil?
{ reason: DevCycle::DEFAULT_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::USER_NOT_TARGETED}
else
if variable_pb.eval.nil?
{ reason: DevCycle::DEFAULT_REASONS::USER_NOT_TARGETED, details: DevCycle::DEFAULT_REASON_DETAILS::USER_NOT_TARGETED }
else
{ reason: variable_pb.eval.reason, details: variable_pb.eval.details, target_id: variable_pb.eval.target_id }
end
end
end

# Adds an eval hook to the client
# @param [EvalHook] eval_hook The eval hook to add
# @return [void]
Expand Down
71 changes: 71 additions & 0 deletions lib/devcycle-ruby-server-sdk/eval_reasons.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
module DevCycle
# Default reasons for evaluation failures
module DEFAULT_REASONS
MISSING_CONFIG = 'MISSING_CONFIG'
MISSING_VARIABLE = 'MISSING_VARIABLE'
MISSING_FEATURE = 'MISSING_FEATURE'
MISSING_VARIATION = 'MISSING_VARIATION'
MISSING_VARIABLE_FOR_VARIATION = 'MISSING_VARIABLE_FOR_VARIATION'
USER_NOT_IN_ROLLOUT = 'USER_NOT_IN_ROLLOUT'
USER_NOT_TARGETED = 'USER_NOT_TARGETED'
INVALID_VARIABLE_TYPE = 'INVALID_VARIABLE_TYPE'
UNKNOWN = 'UNKNOWN'
DEFAULT = 'DEFAULT'
end

# Evaluation reasons for successful evaluations
module EVAL_REASONS
TARGETING_MATCH = 'TARGETING_MATCH'
SPLIT = 'SPLIT'
DEFAULT = 'DEFAULT'
DISABLED = 'DISABLED'
ERROR = 'ERROR'
OVERRIDE = 'OVERRIDE'
OPT_IN = 'OPT_IN'
end

# Detailed evaluation reason descriptions
module EVAL_REASON_DETAILS
# All Users
ALL_USERS = 'All Users'
# Audiences
AUDIENCE_MATCH = 'Audience Match'
NOT_IN_AUDIENCE = 'Not in Audience'
# Opt-In
OPT_IN = 'Opt-In'
NOT_OPTED_IN = 'Not Opt-In'
# Overrides
OVERRIDE = 'Override'
# Split details
RANDOM_DISTRIBUTION = 'Random Distribution'
ROLLOUT = 'Rollout'
# User Specific
USER_ID = 'User ID'
EMAIL = 'Email'
COUNTRY = 'Country'
PLATFORM = 'Platform'
PLATFORM_VERSION = 'Platform Version'
APP_VERSION = 'App Version'
DEVICE_MODEL = 'Device Model'
CUSTOM_DATA = 'Custom Data'
# Error cases
ERROR = 'Error'
DEFAULT = 'Default'
UNKNOWN = 'Unknown'
end

# Default reason details
module DEFAULT_REASON_DETAILS
MISSING_CONFIG = 'Missing Config'
MISSING_VARIABLE = 'Missing Variable'
MISSING_FEATURE = 'Missing Feature'
MISSING_VARIATION = 'Missing Variation'
MISSING_VARIABLE_FOR_VARIATION = 'Missing Variable for Variation'
USER_NOT_IN_ROLLOUT = 'User Not in Rollout'
USER_NOT_TARGETED = 'User Not Targeted'
INVALID_VARIABLE_TYPE = 'Invalid Variable Type'
TYPE_MISMATCH = 'Variable Type Mismatch'
UNKNOWN = 'Unknown'
ERROR = 'Error'
end
end
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,12 @@ message SDKVariable_PB {
double doubleValue = 5;
string stringValue = 6;
NullableString evalReason = 7;
NullableString _feature = 8;
EvalReason_PB eval = 9;
}

message EvalReason_PB {
string reason = 1;
string details = 2;
string target_id = 3;
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions lib/devcycle-ruby-server-sdk/localbucketing/update_wasm.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
BUCKETING_LIB_VERSION="1.35.1"
BUCKETING_LIB_VERSION="1.41.0"
WAT_DOWNLOAD=0
rm bucketing-lib.release.wasm
wget "https://unpkg.com/@devcycle/bucketing-assembly-script@$BUCKETING_LIB_VERSION/build/bucketing-lib.release.wasm"
wget "https://unpkg.com/@devcycle/bucketing-assembly-script@$BUCKETING_LIB_VERSION/build/bucketing-lib.release.wasm"
10 changes: 9 additions & 1 deletion lib/devcycle-ruby-server-sdk/models/variable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class Variable

attr_accessor :defaultValue

# Variable evaluation details
attr_accessor :eval

class EnumAttributeValidator
attr_reader :datatype
attr_reader :allowable_values
Expand Down Expand Up @@ -58,7 +61,8 @@ def self.attribute_map
:'type' => :'type',
:'value' => :'value',
:'defaultValue' => :'defaultValue',
:'isDefaulted' => :'isDefaulted'
:'isDefaulted' => :'isDefaulted',
:'eval' => :'eval'
}
end

Expand Down Expand Up @@ -120,6 +124,10 @@ def initialize(attributes = {})
if attributes.key?(:'defaultValue')
self.defaultValue = attributes[:'defaultValue']
end

if attributes.key?(:'eval')
self.eval = attributes[:'eval']
end
end

# Show invalid properties with the reasons. Usually used together with valid?
Expand Down
20 changes: 11 additions & 9 deletions spec/api/devcycle_api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@
sdk_key = ENV["DEVCYCLE_SERVER_SDK_KEY"]
if sdk_key.nil?
puts("SDK KEY NOT SET - SKIPPING INIT")
return
@skip_tests = true
else
# run before each test
options = DevCycle::Options.new(enable_cloud_bucketing: true)
@api_instance = DevCycle::Client.new(sdk_key, options)

@user = DevCycle::User.new({
user_id: 'test-user',
appVersion: '1.2.3'
})
@skip_tests = false
end
# run before each test
options = DevCycle::Options.new(enable_cloud_bucketing: true)
@api_instance = DevCycle::Client.new(sdk_key, options)

@user = DevCycle::User.new({
user_id: 'test-user',
appVersion: '1.2.3'
})
end

after do
Expand Down
Loading