Class: FlagDash::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/flagdash.rb

Constant Summary collapse

REGION_ENV =
%w[FLAGDASH_REGION FLY_REGION AWS_REGION AWS_DEFAULT_REGION VERCEL_REGION GOOGLE_CLOUD_REGION RAILWAY_REPLICA_REGION RENDER_REGION].freeze

Instance Method Summary collapse

Constructor Details

#initialize(sdk_key:, base_url: "https://flagdash.io", timeout: 5, cache_ttl: 60, region: nil, transport: nil) ⇒ Client

Returns a new instance of Client.

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/flagdash.rb', line 14

def initialize(sdk_key:, base_url: "https://flagdash.io", timeout: 5, cache_ttl: 60, region: nil, transport: nil)
  raise ArgumentError, "sdk_key is required" if sdk_key.to_s.empty?

  @sdk_key = sdk_key
  @base_url = base_url.delete_suffix("/")
  @timeout = timeout
  @cache_ttl = cache_ttl
  @region = region || REGION_ENV.filter_map { |name| ENV[name] }.first
  @transport = transport || method(:http_request)
  @cache = {}
  @mutex = Mutex.new
  @events = []
end

Instance Method Details

#ai_config(file_name) ⇒ Object



69
70
71
72
73
# File 'lib/flagdash.rb', line 69

def ai_config(file_name)
  cached("ai:#{file_name}") { request(:get, "/server/ai-configs/#{segment(file_name)}")["ai_config"] }
rescue StandardError
  nil
end

#all_flags(context: nil) ⇒ Object



43
44
45
46
47
# File 'lib/flagdash.rb', line 43

def all_flags(context: nil)
  return fetch_flags(context) if context && !context.empty?

  cached("all_flags") { fetch_flags(nil) }
end

#clear_cacheObject



125
126
127
# File 'lib/flagdash.rb', line 125

def clear_cache
  @mutex.synchronize { @cache.clear }
end

#closeObject



129
130
131
# File 'lib/flagdash.rb', line 129

def close
  flush
end

#config(key, default: nil) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/flagdash.rb', line 53

def config(key, default: nil)
  cached("config:#{key}") do
    request(:get, "/server/configs/#{segment(key)}").fetch("config", {}).fetch("value", default)
  end
rescue StandardError
  default
end

#experiment(key, context:) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/flagdash.rb', line 96

def experiment(key, context:)
  return nil unless identity(context)

  request(:get, "/server/experiments/#{segment(key)}", params: context_params(context))["experiment"]
rescue StandardError
  nil
end

#flag(key, default: false, context: nil) ⇒ Object



28
29
30
31
32
# File 'lib/flagdash.rb', line 28

def flag(key, default: false, context: nil)
  return flag_detail(key, default: default, context: context).value if context && !context.empty?

  cached("flag:#{key}") { all_flags.fetch(key, default) }
end

#flag_detail(key, default: nil, context: nil) ⇒ Object



34
35
36
37
38
39
40
41
# File 'lib/flagdash.rb', line 34

def flag_detail(key, default: nil, context: nil)
  data = request(:get, "/server/flags/#{segment(key)}", params: context_params(context))
  flag = data.fetch("flag")
  Detail.new(key: flag.fetch("key", key), value: flag.fetch("evaluated_value", default),
             reason: flag.fetch("evaluation_path", "default"), variation_key: flag["variation_key"])
rescue StandardError
  Detail.new(key: key, value: default, reason: "default", variation_key: nil)
end

#flushObject



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/flagdash.rb', line 112

def flush
  loop do
    batch = @mutex.synchronize { @events.first(100) }
    break if batch.empty?

    request(:post, "/server/experiment-events/batch", json: {events: batch})
    @mutex.synchronize { @events.shift(batch.length) }
  end
  true
rescue StandardError
  false
end

#get_config(key) ⇒ Object



61
62
63
# File 'lib/flagdash.rb', line 61

def get_config(key)
  request(:get, "/server/configs/#{segment(key)}")["config"]
end

#list_ai_configs(file_type: nil, folder: :any) ⇒ Object



75
76
77
78
79
# File 'lib/flagdash.rb', line 75

def list_ai_configs(file_type: nil, folder: :any)
  request(:get, "/server/ai-configs").fetch("ai_configs", []).select do |item|
    (!file_type || item["file_type"] == file_type.to_s) && (folder == :any || item["folder"] == folder)
  end
end

#list_configsObject



65
66
67
# File 'lib/flagdash.rb', line 65

def list_configs
  request(:get, "/server/configs").fetch("configs", [])
end

#list_flagsObject



49
50
51
# File 'lib/flagdash.rb', line 49

def list_flags
  request(:get, "/server/flags", params: context_params(nil)).fetch("flags", [])
end

#track_experiment_metric(experiment_key:, event_name:, user_id:, value: nil, properties: {}, event_id: nil, occurred_at: nil) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/flagdash.rb', line 104

def track_experiment_metric(experiment_key:, event_name:, user_id:, value: nil, properties: {}, event_id: nil, occurred_at: nil)
  event = {event_id: event_id || "evt_#{SecureRandom.uuid}", experiment_key: experiment_key,
           event_name: event_name, user_id: user_id, value: value, properties: properties,
           occurred_at: occurred_at || Time.now.utc.iso8601}
  @mutex.synchronize { @events << event if @events.length < 1_000 }
  nil
end

#translation(key, locale:, default: nil, variables: {}) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/flagdash.rb', line 81

def translation(key, locale:, default: nil, variables: {})
  namespace, message = key.split(".", 2)
  return default || key unless message

  catalog = cached("translation:#{locale}:#{namespace}") do
    request(:get, "/server/translations/#{segment(locale)}/#{segment(namespace)}").fetch("catalog", {})
  end
  pattern = catalog.fetch("messages", {})[message]
  return default || key unless pattern

  pattern.gsub(/\{([\w.]+)\}/) { |match| variables.fetch(Regexp.last_match(1), variables.fetch(Regexp.last_match(1).to_sym, match)).to_s }
rescue StandardError
  default || key
end