Class: Quonfig::OpenFeature::Provider

Inherits:
Object
  • Object
show all
Defined in:
lib/quonfig/openfeature/provider.rb

Overview

OpenFeature provider that wraps the quonfig Ruby SDK and implements the OpenFeature server-side provider contract:

* +metadata+
* +init(evaluation_context = nil)+
* +shutdown+
* +fetch_boolean_value(flag_key:, default_value:, evaluation_context:)+
* +fetch_string_value(flag_key:, default_value:, evaluation_context:)+
* +fetch_number_value(flag_key:, default_value:, evaluation_context:)+
* +fetch_integer_value(flag_key:, default_value:, evaluation_context:)+
* +fetch_float_value(flag_key:, default_value:, evaluation_context:)+
* +fetch_object_value(flag_key:, default_value:, evaluation_context:)+

Usage:

require 'quonfig/openfeature'
require 'open_feature/sdk'

provider = Quonfig::OpenFeature::Provider.new(sdk_key: 'qf_sk_...')
OpenFeature::SDK.set_provider_and_wait(provider)

client = OpenFeature::SDK.build_client
client.fetch_boolean_value(flag_key: 'my-flag', default_value: false)

Constant Summary collapse

NAME =
'quonfig'
ResolutionDetails =
::OpenFeature::SDK::Provider::ResolutionDetails
Reason =
::OpenFeature::SDK::Provider::Reason
ErrorCode =
::OpenFeature::SDK::Provider::ErrorCode
ProviderMetadata =
::OpenFeature::SDK::Provider::ProviderMetadata

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sdk_key: nil, datadir: nil, environment: nil, targeting_key_mapping: Context::DEFAULT_TARGETING_KEY_MAPPING, client: nil, **quonfig_options) ⇒ Provider

Returns a new instance of Provider.

Parameters:

  • sdk_key (String, nil) (defaults to: nil)

    SDK key for the live delivery service.

  • datadir (String, nil) (defaults to: nil)

    path to a Quonfig workspace for offline mode.

  • environment (String, nil) (defaults to: nil)

    which environment to evaluate.

  • targeting_key_mapping (String) (defaults to: Context::DEFAULT_TARGETING_KEY_MAPPING)

    dot-notation path the OpenFeature targeting_key is rewritten to (default “user.id”).

  • client (Quonfig::Client, nil) (defaults to: nil)

    inject a pre-built Quonfig client (primarily for tests). When supplied, the other sdk_key/datadir/etc. options are ignored.

  • quonfig_options (Hash)

    any other keyword arguments are forwarded verbatim to Quonfig::Client.new.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/quonfig/openfeature/provider.rb', line 54

def initialize(sdk_key: nil, datadir: nil, environment: nil,
               targeting_key_mapping: Context::DEFAULT_TARGETING_KEY_MAPPING,
               client: nil, **quonfig_options)
  @metadata = ProviderMetadata.new(name: NAME).freeze
  @targeting_key_mapping = targeting_key_mapping
  @client = client
  @quonfig_options = build_quonfig_options(
    sdk_key: sdk_key,
    datadir: datadir,
    environment: environment,
    extra: quonfig_options
  )
  @initialized = !@client.nil?
end

Instance Attribute Details

#metadataObject (readonly)

Returns the value of attribute metadata.



42
43
44
# File 'lib/quonfig/openfeature/provider.rb', line 42

def 
  @metadata
end

#targeting_key_mappingObject (readonly)

Returns the value of attribute targeting_key_mapping.



42
43
44
# File 'lib/quonfig/openfeature/provider.rb', line 42

def targeting_key_mapping
  @targeting_key_mapping
end

Instance Method Details

#clientObject

Escape hatch: returns the underlying Quonfig::Client for native-only features (keys, raw config, durations, log levels). Returns nil until init has run.



92
93
94
# File 'lib/quonfig/openfeature/provider.rb', line 92

def client
  @client
end

#fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object

—- fetch_*_value —————————————————–



98
99
100
101
102
# File 'lib/quonfig/openfeature/provider.rb', line 98

def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    to_resolution(client.get_bool_details(flag_key, context: mapped_ctx), default_value)
  end
end

#fetch_float_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object



129
130
131
132
133
# File 'lib/quonfig/openfeature/provider.rb', line 129

def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    to_resolution(client.get_float_details(flag_key, context: mapped_ctx), default_value)
  end
end

#fetch_integer_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object



123
124
125
126
127
# File 'lib/quonfig/openfeature/provider.rb', line 123

def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    to_resolution(client.get_int_details(flag_key, context: mapped_ctx), default_value)
  end
end

#fetch_number_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/quonfig/openfeature/provider.rb', line 110

def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
  # OpenFeature's "number" is Ruby Numeric (Integer or Float). Try integer
  # first, fall back to float so we transparently handle both Quonfig
  # int and double configs.
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    details = client.get_int_details(flag_key, context: mapped_ctx)
    if details.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
      details = client.get_float_details(flag_key, context: mapped_ctx)
    end
    to_resolution(details, default_value)
  end
end

#fetch_object_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object

Object resolution tries get_string_list_details first (so Quonfig string_list configs surface as native arrays), then falls back to get_json_details for any other JSON-shaped config.



138
139
140
141
142
143
144
145
146
# File 'lib/quonfig/openfeature/provider.rb', line 138

def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    details = client.get_string_list_details(flag_key, context: mapped_ctx)
    if details.error_code == ::Quonfig::EvaluationDetails::ERROR_TYPE_MISMATCH
      details = client.get_json_details(flag_key, context: mapped_ctx)
    end
    to_resolution(details, default_value)
  end
end

#fetch_string_value(flag_key:, default_value:, evaluation_context: nil) ⇒ Object



104
105
106
107
108
# File 'lib/quonfig/openfeature/provider.rb', line 104

def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
  evaluate(flag_key, default_value, evaluation_context) do |client, mapped_ctx|
    to_resolution(client.get_string_details(flag_key, context: mapped_ctx), default_value)
  end
end

#init(_evaluation_context = nil) ⇒ Object

Initialize the underlying Quonfig client. Called by OpenFeature::SDK.set_provider_and_wait.



71
72
73
74
75
76
77
# File 'lib/quonfig/openfeature/provider.rb', line 71

def init(_evaluation_context = nil)
  return if @initialized

  @client = ::Quonfig::Client.new(@quonfig_options)
  @initialized = true
  nil
end

#shutdownObject

Shut the provider down. Mirrors the OpenFeature InMemoryProvider contract — silently no-ops if the client was never built.



81
82
83
84
85
86
87
# File 'lib/quonfig/openfeature/provider.rb', line 81

def shutdown
  client = @client
  @client = nil
  @initialized = false
  client&.stop
  nil
end