Class: DevCycle::ConfigManager

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb

Instance Method Summary collapse

Constructor Details

#initialize(sdkKey, local_bucketing, wait_for_init) ⇒ ConfigManager

Returns a new instance of ConfigManager.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 16

def initialize(sdkKey, local_bucketing, wait_for_init)
  @first_load = true
  @config_version = "v1"
  @local_bucketing = local_bucketing
  @sdkKey = sdkKey
  @config_e_tag = ""
  @logger = local_bucketing.options.logger
  @polling_enabled = true
  @max_config_retries = 2

  @config_poller = Concurrent::TimerTask.new({
      execution_interval: @local_bucketing.options.config_polling_interval_ms.fdiv(1000)
    }) do |task|
    fetch_config
  end

  t = Thread.new { initialize_config }
  t.join if wait_for_init
end

Instance Method Details

#closeObject



114
115
116
117
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 114

def close
  @config_poller.shutdown if @config_poller.running?
  nil
end

#fetch_configObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 47

def fetch_config
  return unless @polling_enabled

  req = Typhoeus::Request.new(
    get_config_url,
    headers: {
      Accept: "application/json",
    })

  if @config_e_tag != ""
    req.options[:headers]['If-None-Match'] = @config_e_tag
  end

  @max_config_retries.times do
    @logger.debug("Requesting new config from #{get_config_url}, current etag: #{@config_e_tag}")
    resp = req.run
    @logger.debug("Config request complete, status: #{resp.code}")
    case resp.code
    when 304
      @logger.debug("Config not modified, using cache, etag: #{@config_e_tag}")
      break
    when 200
      @logger.debug("New config received, etag: #{resp.headers['Etag']}")
      set_config(resp.body, resp.headers['Etag'])
      @logger.debug("New config stored, etag: #{@config_e_tag}")
      break
    when 403
      stop_polling
      @logger.error("Failed to download DevCycle config; Invalid SDK Key.")
      break
    when 404
      stop_polling
      @logger.error("Failed to download DevCycle config; Config not found.")
      break
    when 500...599
      @logger.error("Failed to download DevCycle config. Status: #{resp.code}")
    else
      @logger.error("Unexpected response from DevCycle CDN")
      @logger.error("Response code: #{resp.code}")
      @logger.error("Response body: #{resp.body}")
      break
    end
  end

  nil
end

#get_config_urlObject



104
105
106
107
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 104

def get_config_url
  configBasePath = @local_bucketing.options.config_cdn_uri
  "#{configBasePath}/config/#{@config_version}/server/#{@sdkKey}.json"
end

#initialize_configObject



36
37
38
39
40
41
42
43
44
45
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 36

def initialize_config
  begin
    fetch_config
    @config_poller.execute if @polling_enabled
  rescue => e
    @logger.error("DevCycle: Error Initializing Config: #{e.message}")
  ensure
    @local_bucketing.initialized = true
  end
end

#set_config(config, etag) ⇒ Object



94
95
96
97
98
99
100
101
102
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 94

def set_config(config, etag)
  if !JSON.parse(config).is_a?(Hash)
    raise("Invalid JSON body parsed from Config Response")
  end

  @local_bucketing.store_config(config)
  @config_e_tag = etag
  @local_bucketing.has_config = true
end

#stop_pollingObject



109
110
111
112
# File 'lib/devcycle-ruby-server-sdk/localbucketing/config_manager.rb', line 109

def stop_polling
  @polling_enabled = false
  @config_poller.shutdown if @config_poller.running?
end