eppo-server-sdk 0.2.5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'validation'
4
- require_relative 'assignment_logger'
3
+ require_relative "validation"
4
+ require_relative "assignment_logger"
5
5
 
6
6
  module EppoClient
7
7
  # The class for configuring the Eppo client singleton
8
8
  class Config
9
9
  attr_reader :api_key, :assignment_logger, :base_url
10
10
 
11
- def initialize(api_key, assignment_logger: AssignmentLogger.new, base_url: 'https://fscdn.eppo.cloud/api')
11
+ def initialize(api_key, assignment_logger: AssignmentLogger.new, base_url: EppoClient::Core::DEFAULT_BASE_URL)
12
12
  @api_key = api_key
13
13
  @assignment_logger = assignment_logger
14
14
  @base_url = base_url
15
15
  end
16
16
 
17
17
  def validate
18
- EppoClient.validate_not_blank('api_key', @api_key)
18
+ EppoClient.validate_not_blank("api_key", @api_key)
19
19
  end
20
20
 
21
21
  # Hide instance variables (specifically api_key) from logs
@@ -8,23 +8,6 @@ module EppoClient
8
8
  end
9
9
  end
10
10
 
11
- # A custom error class for unauthorized requests
12
- class UnauthorizedError < StandardError
13
- def initialize(message)
14
- super("Unauthorized: #{message}")
15
- end
16
- end
17
-
18
- # A custom error class for HTTP requests
19
- class HttpRequestError < StandardError
20
- attr_reader :status_code
21
-
22
- def initialize(message, status_code)
23
- @status_code = status_code
24
- super("HttpRequestError: #{message}")
25
- end
26
- end
27
-
28
11
  # A custom error class for invalid values
29
12
  class InvalidValueError < StandardError
30
13
  def initialize(message)
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'custom_errors'
3
+ require_relative "custom_errors"
4
4
 
5
5
  # The helper module to validate keys
6
6
  module EppoClient
7
7
  module_function
8
8
 
9
9
  def validate_not_blank(field_name, field_value)
10
- (field_value.nil? || field_value == '') && raise(
10
+ (field_value.nil? || field_value == "") && raise(
11
11
  EppoClient::InvalidValueError, "#{field_name} cannot be blank"
12
12
  )
13
13
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EppoClient
4
- VERSION = '0.2.5'
4
+ VERSION = "3.0.0"
5
5
  end
data/lib/eppo_client.rb CHANGED
@@ -1,53 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'eppo_client/assignment_logger'
4
- require_relative 'eppo_client/http_client'
5
- require_relative 'eppo_client/poller'
6
- require_relative 'eppo_client/config'
7
- require_relative 'eppo_client/client'
8
- require_relative 'eppo_client/constants'
9
- require_relative 'eppo_client/configuration_requestor'
10
- require_relative 'eppo_client/configuration_store'
11
- require_relative 'eppo_client/version'
3
+ require_relative "eppo_client/client"
4
+ require_relative "eppo_client/version"
12
5
 
13
- # This module scopes all the client SDK's classes and functions
6
+ # EppoClient is the main module for initializing the Eppo client.
7
+ # It provides a method to initialize the client with a given configuration.
14
8
  module EppoClient
15
- # rubocop:disable Metrics/MethodLength
16
- def initialize_client(config_requestor, assignment_logger)
17
- client = EppoClient::Client.instance
18
- !client.poller.nil? && client.shutdown
19
- client.config_requestor = config_requestor
20
- client.assignment_logger = assignment_logger
21
- client.poller = EppoClient::Poller.new(
22
- EppoClient::POLL_INTERVAL_MILLIS,
23
- EppoClient::POLL_JITTER_MILLIS,
24
- proc { client.config_requestor.fetch_and_store_configurations }
25
- )
26
- client.poller.start
27
- client
28
- end
29
- # rubocop:enable Metrics/MethodLength
30
-
31
- # rubocop:disable Metrics/MethodLength
32
9
  def init(config)
33
- config.validate
34
- sdk_params = EppoClient::SdkParams.new(config.api_key, 'ruby',
35
- EppoClient::VERSION)
36
- http_client = EppoClient::HttpClient.new(config.base_url,
37
- sdk_params.formatted)
38
- config_store = EppoClient::ConfigurationStore.new(
39
- EppoClient::MAX_CACHE_ENTRIES
40
- )
41
- config_store.lock.with_write_lock do
42
- EppoClient.initialize_client(
43
- EppoClient::ExperimentConfigurationRequestor.new(
44
- http_client, config_store
45
- ),
46
- config.assignment_logger
47
- )
48
- end
10
+ client = EppoClient::Client.instance
11
+ client.init(config)
49
12
  end
50
- # rubocop:enable Metrics/MethodLength
51
13
 
52
- module_function :init, :initialize_client
14
+ module_function :init
53
15
  end
@@ -0,0 +1,96 @@
1
+ # EppoClient is the main module for initializing the Eppo client.
2
+ # It provides a method to initialize the client with a given configuration.
3
+ module EppoClient
4
+ def self.init: (Config config) -> void
5
+
6
+ # The base assignment logger class to override
7
+ class AssignmentLogger
8
+ def log_assignment: (untyped assignment_event) -> void
9
+
10
+ def log_bandit_action: (untyped assignment_event) -> void
11
+ end
12
+
13
+ # The main client singleton
14
+ class Client
15
+ @assignment_logger: AssignmentLogger
16
+ @core: Core::Client
17
+
18
+ include Singleton
19
+
20
+ attr_accessor assignment_logger: AssignmentLogger
21
+
22
+ def self.instance: () -> Client
23
+
24
+ def init: (Config config) -> void
25
+
26
+ def shutdown: () -> void
27
+
28
+ def get_string_assignment: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, String default_value) -> String
29
+
30
+ def get_numeric_assignment: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, Numeric default_value) -> Numeric
31
+
32
+ def get_integer_assignment: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, Integer default_value) -> Integer
33
+
34
+ def get_boolean_assignment: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, bool default_value) -> bool
35
+
36
+ def get_json_assignment: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, Object default_value) -> Object
37
+
38
+ def get_bandit_action: (String flag_key, String subject_key, Hash[String, untyped] subject_attributes, Hash[String, untyped] actions, String default_variation) -> { variation: untyped, action: untyped }
39
+
40
+ private
41
+
42
+ # rubocop:disable Metrics/MethodLength
43
+ def get_assignment_inner: (untyped flag_key, String subject_key, untyped subject_attributes, untyped expected_type, untyped default_value) -> untyped
44
+
45
+ def log_assignment: (untyped event) -> void
46
+
47
+ def log_bandit_action: (untyped event) -> void
48
+
49
+ def enrich_event_metadata: (untyped event) -> void
50
+
51
+ def coerce_context_attributes: (untyped attributes) -> untyped
52
+ end
53
+
54
+ # The class for configuring the Eppo client singleton
55
+ class Config
56
+ @api_key: String
57
+ @assignment_logger: AssignmentLogger
58
+ @base_url: String
59
+
60
+ attr_reader api_key: String
61
+ attr_reader assignment_logger: AssignmentLogger
62
+ attr_reader base_url: String
63
+
64
+ def initialize: (String api_key, ?assignment_logger: AssignmentLogger, ?base_url: String) -> void
65
+
66
+ def validate: () -> void
67
+
68
+ # Hide instance variables (specifically api_key) from logs
69
+ def inspect: () -> ::String
70
+ end
71
+
72
+ # A custom error class for AssignmentLogger
73
+ class AssignmentLoggerError < StandardError
74
+ def initialize: (String message) -> void
75
+ end
76
+
77
+ # A custom error class for invalid values
78
+ class InvalidValueError < StandardError
79
+ def initialize: (String message) -> void
80
+ end
81
+
82
+ def self?.validate_not_blank: (String field_name, String field_value) -> void
83
+
84
+ VERSION: String
85
+ end
86
+
87
+ # Exposed from Rust
88
+ module EppoClient::Core
89
+ DEFAULT_BASE_URL: String
90
+ class Client
91
+ def self.new: (untyped config) -> Client
92
+ def shutdown: () -> void
93
+ def get_assignment: (String flag_key, String subject_key, untyped subject_attributes, String expected_type) -> untyped
94
+ def get_bandit_action: (String flag_key, String subject_key, untyped attributes, untyped actions, String default_variation) -> untyped
95
+ end
96
+ end
metadata CHANGED
@@ -1,171 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eppo-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eppo
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-21 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: concurrent-ruby
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.1'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 1.1.9
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '1.1'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: 1.1.9
33
- - !ruby/object:Gem::Dependency
34
- name: faraday
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.7'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 2.7.1
43
- type: :runtime
44
- prerelease: false
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '2.7'
50
- - - ">="
51
- - !ruby/object:Gem::Version
52
- version: 2.7.1
53
- - !ruby/object:Gem::Dependency
54
- name: faraday-retry
55
- requirement: !ruby/object:Gem::Requirement
56
- requirements:
57
- - - "~>"
58
- - !ruby/object:Gem::Version
59
- version: '2.0'
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 2.0.0
63
- type: :runtime
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '2.0'
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 2.0.0
73
- - !ruby/object:Gem::Dependency
74
- name: rake
75
- requirement: !ruby/object:Gem::Requirement
76
- requirements:
77
- - - "~>"
78
- - !ruby/object:Gem::Version
79
- version: '13.0'
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: 13.0.6
83
- type: :development
84
- prerelease: false
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '13.0'
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- version: 13.0.6
93
- - !ruby/object:Gem::Dependency
94
- name: rspec
95
- requirement: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - "~>"
98
- - !ruby/object:Gem::Version
99
- version: '3.12'
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: 3.12.0
103
- type: :development
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '3.12'
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: 3.12.0
113
- - !ruby/object:Gem::Dependency
114
- name: rubocop
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - "~>"
118
- - !ruby/object:Gem::Version
119
- version: 0.82.0
120
- type: :development
121
- prerelease: false
122
- version_requirements: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - "~>"
125
- - !ruby/object:Gem::Version
126
- version: 0.82.0
127
- - !ruby/object:Gem::Dependency
128
- name: webmock
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - "~>"
132
- - !ruby/object:Gem::Version
133
- version: '3.18'
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- version: 3.18.1
137
- type: :development
138
- prerelease: false
139
- version_requirements: !ruby/object:Gem::Requirement
140
- requirements:
141
- - - "~>"
142
- - !ruby/object:Gem::Version
143
- version: '3.18'
144
- - - ">="
145
- - !ruby/object:Gem::Version
146
- version: 3.18.1
147
- description:
148
- email: eppo-team@geteppo.com
11
+ date: 2024-07-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - eppo-team@geteppo.com
149
16
  executables: []
150
- extensions: []
17
+ extensions:
18
+ - ext/eppo_client/Cargo.toml
151
19
  extra_rdoc_files: []
152
20
  files:
21
+ - ".gitignore"
22
+ - ".rspec"
23
+ - ".rubocop.yml"
24
+ - Cargo.lock
25
+ - Cargo.toml
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - Steepfile
30
+ - ext/eppo_client/Cargo.toml
31
+ - ext/eppo_client/build.rs
32
+ - ext/eppo_client/extconf.rb
33
+ - ext/eppo_client/src/client.rs
34
+ - ext/eppo_client/src/lib.rs
153
35
  - lib/eppo_client.rb
154
36
  - lib/eppo_client/assignment_logger.rb
155
37
  - lib/eppo_client/client.rb
156
38
  - lib/eppo_client/config.rb
157
- - lib/eppo_client/configuration_requestor.rb
158
- - lib/eppo_client/configuration_store.rb
159
- - lib/eppo_client/constants.rb
160
39
  - lib/eppo_client/custom_errors.rb
161
- - lib/eppo_client/http_client.rb
162
- - lib/eppo_client/lru_cache.rb
163
- - lib/eppo_client/poller.rb
164
- - lib/eppo_client/rules.rb
165
- - lib/eppo_client/shard.rb
166
40
  - lib/eppo_client/validation.rb
167
- - lib/eppo_client/variation_type.rb
168
41
  - lib/eppo_client/version.rb
42
+ - sig/eppo_server_sdk.rbs
169
43
  homepage: https://github.com/Eppo-exp/ruby-sdk
170
44
  licenses:
171
45
  - MIT
@@ -175,7 +49,7 @@ metadata:
175
49
  homepage_uri: https://geteppo.com/
176
50
  source_code_uri: https://github.com/Eppo-exp/ruby-sdk
177
51
  wiki_uri: https://github.com/Eppo-exp/ruby-sdk/wiki
178
- post_install_message:
52
+ post_install_message:
179
53
  rdoc_options: []
180
54
  require_paths:
181
55
  - lib
@@ -183,15 +57,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
57
  requirements:
184
58
  - - ">="
185
59
  - !ruby/object:Gem::Version
186
- version: 3.0.6
60
+ version: 3.0.0
187
61
  required_rubygems_version: !ruby/object:Gem::Requirement
188
62
  requirements:
189
63
  - - ">="
190
64
  - !ruby/object:Gem::Version
191
- version: '0'
65
+ version: 3.3.11
192
66
  requirements: []
193
- rubygems_version: 3.4.6
194
- signing_key:
67
+ rubygems_version: 3.5.9
68
+ signing_key:
195
69
  specification_version: 4
196
70
  summary: Eppo SDK for Ruby
197
71
  test_files: []
@@ -1,108 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'custom_errors'
4
- require_relative 'constants'
5
-
6
- module EppoClient
7
- # A class for the variation object
8
- class VariationDto
9
- attr_reader :name, :value, :typed_value, :shard_range
10
-
11
- def initialize(name, value, typed_value, shard_range)
12
- @name = name
13
- @value = value
14
- @typed_value = typed_value
15
- @shard_range = shard_range
16
- end
17
- end
18
-
19
- # A class for the allocation object
20
- class AllocationDto
21
- attr_reader :percent_exposure, :variations
22
-
23
- def initialize(percent_exposure, variations)
24
- @percent_exposure = percent_exposure
25
- @variations = variations
26
- end
27
- end
28
-
29
- # A class for the experiment configuration object
30
- class ExperimentConfigurationDto
31
- attr_reader :subject_shards, :enabled, :name, :overrides,
32
- :typed_overrides, :rules, :allocations
33
-
34
- def initialize(exp_config)
35
- @subject_shards = exp_config['subjectShards']
36
- @enabled = exp_config['enabled']
37
- @name = exp_config['name'] || nil
38
- @overrides = exp_config['overrides'] || {}
39
- @typed_overrides = exp_config['typedOverrides'] || {}
40
- @rules = exp_config['rules'] || []
41
- @allocations = exp_config['allocations']
42
- end
43
- end
44
-
45
- # A class for getting exp configs from the local cache or API
46
- class ExperimentConfigurationRequestor
47
- attr_reader :config_store
48
-
49
- def initialize(http_client, config_store)
50
- @http_client = http_client
51
- @config_store = config_store
52
- end
53
-
54
- def get_configuration(experiment_key)
55
- @http_client.is_unauthorized && raise(EppoClient::UnauthorizedError,
56
- 'please check your API key')
57
- @config_store.retrieve_configuration(experiment_key)
58
- end
59
-
60
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
61
- def fetch_and_store_configurations
62
- configs = {}
63
- begin
64
- exp_configs = @http_client.get(EppoClient::RAC_ENDPOINT).fetch(
65
- 'flags', {}
66
- )
67
- # rubocop: disable Metrics/BlockLength
68
- exp_configs.each do |exp_key, exp_config|
69
- exp_config['allocations'].each do |k, v|
70
- exp_config['allocations'][k] = EppoClient::AllocationDto.new(
71
- v['percentExposure'],
72
- v['variations'].map do |var|
73
- EppoClient::VariationDto.new(
74
- var['name'], var['value'], var['typedValue'],
75
- EppoClient::ShardRange.new(var['shardRange']['start'],
76
- var['shardRange']['end'])
77
- )
78
- end
79
- )
80
- end
81
- exp_config['rules'] = exp_config['rules'].map do |rule|
82
- EppoClient::Rule.new(
83
- conditions: rule['conditions'].map do |condition|
84
- EppoClient::Condition.new(
85
- value: condition['value'],
86
- operator: condition['operator'],
87
- attribute: condition['attribute']
88
- )
89
- end,
90
- allocation_key: rule['allocationKey']
91
- )
92
- end
93
- configs[exp_key] = EppoClient::ExperimentConfigurationDto.new(
94
- exp_config
95
- )
96
- end
97
- # rubocop: enable Metrics/BlockLength
98
- @config_store.assign_configurations(configs)
99
- rescue EppoClient::HttpRequestError => e
100
- Logger.new($stdout).error(
101
- "Error retrieving assignment configurations: #{e}"
102
- )
103
- end
104
- configs
105
- end
106
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
107
- end
108
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'concurrent/atomic/read_write_lock'
4
-
5
- require_relative 'lru_cache'
6
-
7
- module EppoClient
8
- # A thread safe store for the configurations to ensure that retrievals pull from a single source of truth
9
- class ConfigurationStore
10
- attr_reader :lock, :cache
11
-
12
- def initialize(max_size)
13
- @cache = EppoClient::LRUCache.new(max_size)
14
- @lock = Concurrent::ReadWriteLock.new
15
- end
16
-
17
- def retrieve_configuration(key)
18
- @lock.with_read_lock { @cache[key] }
19
- end
20
-
21
- def assign_configurations(configs)
22
- @lock.with_write_lock do
23
- # Create a temporary new cache and populate it.
24
- new_cache = EppoClient::LRUCache.new(@cache.size)
25
- configs.each do |key, config|
26
- new_cache[key] = config
27
- end
28
-
29
- # Replace the old cache with the new one.
30
- # Performs an atomic swap.
31
- @cache = new_cache
32
- end
33
- end
34
- end
35
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'logger'
4
-
5
- module EppoClient
6
- # default level for logging
7
- DEFAULT_LOGGER_LEVEL = Logger::INFO
8
-
9
- # configuration cache constants
10
- MAX_CACHE_ENTRIES = 1000 # arbitrary; the caching library requires a max limit
11
-
12
- # poller constants
13
- SECOND_MILLIS = 1000
14
- MINUTE_MILLIS = 60 * SECOND_MILLIS
15
- POLL_JITTER_MILLIS = 30 * SECOND_MILLIS
16
- POLL_INTERVAL_MILLIS = 5 * MINUTE_MILLIS
17
-
18
- # the configs endpoint
19
- RAC_ENDPOINT = 'randomized_assignment/v3/config'
20
- end
@@ -1,75 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'faraday'
4
- require 'faraday/retry'
5
-
6
- require_relative 'custom_errors'
7
-
8
- REQUEST_TIMEOUT_SECONDS = 2
9
- # This applies only to failed DNS lookups and connection timeouts,
10
- # never to requests where data has made it to the server.
11
- MAX_RETRIES = 3
12
-
13
- module EppoClient
14
- # The SDK params object
15
- class SdkParams
16
- attr_reader :api_key, :sdk_name, :sdk_version
17
-
18
- def initialize(api_key, sdk_name, sdk_version)
19
- @api_key = api_key
20
- @sdk_name = sdk_name
21
- @sdk_version = sdk_version
22
- end
23
-
24
- # attributes are camelCase because that's what the backend endpoint expects
25
- def formatted
26
- {
27
- 'apiKey' => api_key,
28
- 'sdkName' => sdk_name,
29
- 'sdkVersion' => sdk_version
30
- }
31
- end
32
-
33
- # Hide instance variables (specifically api_key) from logs
34
- def inspect
35
- "#<EppoClient::SdkParams:#{object_id}>"
36
- end
37
- end
38
-
39
- # The http request client with retry/timeout behavior
40
- class HttpClient
41
- attr_reader :is_unauthorized
42
-
43
- @retry_options = {
44
- max: MAX_RETRIES,
45
- interval: 0.05,
46
- interval_randomness: 0.5,
47
- backoff_factor: 2,
48
- exceptions: ['Timeout::Error']
49
- }
50
-
51
- def initialize(base_url, sdk_params)
52
- @base_url = base_url
53
- @sdk_params = sdk_params
54
- @is_unauthorized = false
55
- end
56
-
57
- def get(resource)
58
- conn = Faraday::Connection.new(@base_url, params: @sdk_params) do |f|
59
- f.request :retry, @retry_options
60
- end
61
- conn.options.timeout = REQUEST_TIMEOUT_SECONDS
62
- response = conn.get(resource)
63
- @is_unauthorized = response.status == 401
64
- raise get_http_error(response.status, resource) if response.status != 200
65
-
66
- JSON.parse(response.body)
67
- end
68
-
69
- private
70
-
71
- def get_http_error(status_code, resource)
72
- EppoClient::HttpRequestError.new("HTTP #{status_code} error while requesting resource #{resource}", status_code)
73
- end
74
- end
75
- end