Class: Feat::Client

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

Overview

Polling HTTP client. Uses stdlib only - zero gem dependencies.

Constant Summary collapse

DEFAULT_POLL_INTERVAL =
30.0
MIN_POLL_INTERVAL =
5.0
MAX_DATAFILE_BYTES =
10 * 1024 * 1024

Instance Method Summary collapse

Constructor Details

#initialize(api_key:, data_plane_url:, poll_interval: DEFAULT_POLL_INTERVAL, http_client: nil) ⇒ Client

Returns a new instance of Client.

Raises:

  • (ArgumentError)


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/feat/client.rb', line 12

def initialize(api_key:, data_plane_url:, poll_interval: DEFAULT_POLL_INTERVAL, http_client: nil)
  raise ArgumentError, "api_key is required" if api_key.nil? || api_key.empty?
  raise ArgumentError, "data_plane_url is required" if data_plane_url.nil? || data_plane_url.empty?

  assert_https_url!(data_plane_url)

  @api_key       = api_key
  @data_plane_url = data_plane_url.chomp("/")
  @poll_interval = [poll_interval.to_f, MIN_POLL_INTERVAL].max
  @http_client   = http_client
  @datafile      = nil
  @etag          = nil
  @mutex         = Mutex.new
  @stop          = false
  @thread        = nil
end

Instance Method Details

#closeObject



35
36
37
# File 'lib/feat/client.rb', line 35

def close
  @stop = true
end

#evaluate(flag_key, default_value, ctx) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/feat/client.rb', line 43

def evaluate(flag_key, default_value, ctx)
  df = @datafile
  if df.nil?
    return EvaluationResult.new(
      value: default_value, reason: Reason::ERROR,
      error_message: "client not ready: call #start before #evaluate"
    )
  end
  Eval.call(flag_key: flag_key, default_value: default_value, ctx: ctx, datafile: df)
end

#get_boolean_value(flag_key, default, ctx) ⇒ Object



54
55
56
57
# File 'lib/feat/client.rb', line 54

def get_boolean_value(flag_key, default, ctx)
  r = evaluate(flag_key, default, ctx)
  r.value == true || r.value == false ? r.value : default
end

#get_number_value(flag_key, default, ctx) ⇒ Object



64
65
66
67
# File 'lib/feat/client.rb', line 64

def get_number_value(flag_key, default, ctx)
  r = evaluate(flag_key, default, ctx)
  r.value.is_a?(Numeric) && !(r.value == true || r.value == false) ? r.value : default
end

#get_object_value(flag_key, default, ctx) ⇒ Object



69
70
71
72
# File 'lib/feat/client.rb', line 69

def get_object_value(flag_key, default, ctx)
  r = evaluate(flag_key, default, ctx)
  r.value
end

#get_string_value(flag_key, default, ctx) ⇒ Object



59
60
61
62
# File 'lib/feat/client.rb', line 59

def get_string_value(flag_key, default, ctx)
  r = evaluate(flag_key, default, ctx)
  r.value.is_a?(String) ? r.value : default
end

#refreshObject



39
40
41
# File 'lib/feat/client.rb', line 39

def refresh
  fetch_once
end

#startObject

Blocking initial fetch; spawns a background poller thread.



30
31
32
33
# File 'lib/feat/client.rb', line 30

def start
  refresh
  @thread ||= Thread.new { poll_loop }
end