eppo-server-sdk 3.1.1 → 3.2.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.
- checksums.yaml +4 -4
- data/Cargo.lock +24 -5
- data/ext/eppo_client/Cargo.toml +4 -3
- data/ext/eppo_client/src/client.rs +58 -28
- data/ext/eppo_client/src/configuration.rs +113 -0
- data/ext/eppo_client/src/gc_lock.rs +25 -0
- data/ext/eppo_client/src/lib.rs +21 -1
- data/lib/eppo_client/client.rb +8 -0
- data/lib/eppo_client/config.rb +4 -2
- data/lib/eppo_client/version.rb +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cd858b9082e0b7d776c90f73c086271ac4e7983c7c0d981f060cc44ee2953b1
|
4
|
+
data.tar.gz: 9fa7706a5fc234775980808cafed2924322b8d4db797fe878346b78da8b34d8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb6fa1371ed76e2c0f041625ac1aa336ae13c2fe303e722749efb4ddf9b9e7d0ba1536978b8d889e78f1e573a8021be0f9396f51a0f623dcaac1f7e66c4e9c75
|
7
|
+
data.tar.gz: bb022578cba95db2cdfae89cc1431abaf30cb7c83875f18ee8ca1d9feecfb93e735aa72d3e9990d59a4e718d401ec95d65063ccc2d3aef57d8f0a1ae5f2d6410
|
data/Cargo.lock
CHANGED
@@ -304,7 +304,7 @@ dependencies = [
|
|
304
304
|
|
305
305
|
[[package]]
|
306
306
|
name = "eppo_client"
|
307
|
-
version = "3.
|
307
|
+
version = "3.2.0"
|
308
308
|
dependencies = [
|
309
309
|
"env_logger",
|
310
310
|
"eppo_core",
|
@@ -312,17 +312,19 @@ dependencies = [
|
|
312
312
|
"magnus",
|
313
313
|
"rb-sys",
|
314
314
|
"serde",
|
315
|
+
"serde_json",
|
315
316
|
"serde_magnus",
|
316
317
|
]
|
317
318
|
|
318
319
|
[[package]]
|
319
320
|
name = "eppo_core"
|
320
|
-
version = "
|
321
|
+
version = "4.0.0"
|
321
322
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
322
|
-
checksum = "
|
323
|
+
checksum = "b071fed21065318dcd6a91a443bd9f6b39796d727297b03d092e2e8dc9e02414"
|
323
324
|
dependencies = [
|
324
325
|
"chrono",
|
325
326
|
"derive_more",
|
327
|
+
"faststr",
|
326
328
|
"log",
|
327
329
|
"md5",
|
328
330
|
"rand",
|
@@ -367,6 +369,17 @@ version = "2.1.0"
|
|
367
369
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
368
370
|
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
369
371
|
|
372
|
+
[[package]]
|
373
|
+
name = "faststr"
|
374
|
+
version = "0.2.23"
|
375
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
376
|
+
checksum = "4dc21a7d5a45182c2bb5ae9471b93f10919c0744b54403e54a9e2329c26ed5a3"
|
377
|
+
dependencies = [
|
378
|
+
"bytes",
|
379
|
+
"serde",
|
380
|
+
"simdutf8",
|
381
|
+
]
|
382
|
+
|
370
383
|
[[package]]
|
371
384
|
name = "fnv"
|
372
385
|
version = "1.0.7"
|
@@ -1283,9 +1296,9 @@ dependencies = [
|
|
1283
1296
|
|
1284
1297
|
[[package]]
|
1285
1298
|
name = "serde_json"
|
1286
|
-
version = "1.0.
|
1299
|
+
version = "1.0.128"
|
1287
1300
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1288
|
-
checksum = "
|
1301
|
+
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
1289
1302
|
dependencies = [
|
1290
1303
|
"itoa",
|
1291
1304
|
"memchr",
|
@@ -1328,6 +1341,12 @@ version = "1.3.0"
|
|
1328
1341
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1329
1342
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
1330
1343
|
|
1344
|
+
[[package]]
|
1345
|
+
name = "simdutf8"
|
1346
|
+
version = "0.1.5"
|
1347
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
1348
|
+
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
1349
|
+
|
1331
1350
|
[[package]]
|
1332
1351
|
name = "slab"
|
1333
1352
|
version = "0.4.9"
|
data/ext/eppo_client/Cargo.toml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[package]
|
2
2
|
name = "eppo_client"
|
3
3
|
# TODO: this version and lib/eppo_client/version.rb should be in sync
|
4
|
-
version = "3.
|
4
|
+
version = "3.2.0"
|
5
5
|
edition = "2021"
|
6
6
|
license = "MIT"
|
7
7
|
publish = false
|
@@ -12,9 +12,10 @@ crate-type = ["cdylib"]
|
|
12
12
|
|
13
13
|
[dependencies]
|
14
14
|
env_logger = { version = "0.11.3", features = ["unstable-kv"] }
|
15
|
-
eppo_core = { version = "
|
15
|
+
eppo_core = { version = "4.0.0" }
|
16
16
|
log = { version = "0.4.21", features = ["kv_serde"] }
|
17
|
-
magnus = { version = "0.6.
|
17
|
+
magnus = { version = "0.6.4" }
|
18
18
|
serde = { version = "1.0.203", features = ["derive"] }
|
19
19
|
serde_magnus = "0.8.1"
|
20
20
|
rb-sys = "0.9"
|
21
|
+
serde_json = "1.0.128"
|
@@ -1,20 +1,24 @@
|
|
1
|
-
use std::{cell::RefCell, sync::Arc};
|
1
|
+
use std::{cell::RefCell, sync::Arc, time::Duration};
|
2
2
|
|
3
3
|
use eppo_core::{
|
4
4
|
configuration_fetcher::{ConfigurationFetcher, ConfigurationFetcherConfig},
|
5
5
|
configuration_store::ConfigurationStore,
|
6
6
|
eval::{Evaluator, EvaluatorConfig},
|
7
|
-
poller_thread::PollerThread,
|
7
|
+
poller_thread::{PollerThread, PollerThreadConfig},
|
8
8
|
ufc::VariationType,
|
9
|
-
Attributes, ContextAttributes,
|
9
|
+
Attributes, ContextAttributes,
|
10
10
|
};
|
11
11
|
use magnus::{error::Result, exception, prelude::*, Error, TryConvert, Value};
|
12
12
|
|
13
|
+
use crate::{configuration::Configuration, SDK_METADATA};
|
14
|
+
|
13
15
|
#[derive(Debug)]
|
14
16
|
#[magnus::wrap(class = "EppoClient::Core::Config", size, free_immediately)]
|
15
17
|
pub struct Config {
|
16
18
|
api_key: String,
|
17
19
|
base_url: String,
|
20
|
+
poll_interval: Option<Duration>,
|
21
|
+
poll_jitter: Duration,
|
18
22
|
}
|
19
23
|
|
20
24
|
impl TryConvert for Config {
|
@@ -22,12 +26,21 @@ impl TryConvert for Config {
|
|
22
26
|
fn try_convert(val: magnus::Value) -> Result<Self> {
|
23
27
|
let api_key = String::try_convert(val.funcall("api_key", ())?)?;
|
24
28
|
let base_url = String::try_convert(val.funcall("base_url", ())?)?;
|
25
|
-
|
29
|
+
let poll_interval_seconds =
|
30
|
+
Option::<u64>::try_convert(val.funcall("poll_interval_seconds", ())?)?;
|
31
|
+
let poll_jitter_seconds = u64::try_convert(val.funcall("poll_jitter_seconds", ())?)?;
|
32
|
+
Ok(Config {
|
33
|
+
api_key,
|
34
|
+
base_url,
|
35
|
+
poll_interval: poll_interval_seconds.map(Duration::from_secs),
|
36
|
+
poll_jitter: Duration::from_secs(poll_jitter_seconds),
|
37
|
+
})
|
26
38
|
}
|
27
39
|
}
|
28
40
|
|
29
41
|
#[magnus::wrap(class = "EppoClient::Core::Client")]
|
30
42
|
pub struct Client {
|
43
|
+
configuration_store: Arc<ConfigurationStore>,
|
31
44
|
evaluator: Evaluator,
|
32
45
|
// Magnus only allows sharing aliased references (&T) through the API, so we need to use RefCell
|
33
46
|
// to get interior mutability.
|
@@ -41,29 +54,35 @@ impl Client {
|
|
41
54
|
pub fn new(config: Config) -> Client {
|
42
55
|
let configuration_store = Arc::new(ConfigurationStore::new());
|
43
56
|
|
44
|
-
let
|
45
|
-
|
46
|
-
|
57
|
+
let poller_thread = if let Some(poll_interval) = config.poll_interval {
|
58
|
+
Some(
|
59
|
+
PollerThread::start_with_config(
|
60
|
+
ConfigurationFetcher::new(ConfigurationFetcherConfig {
|
61
|
+
base_url: config.base_url,
|
62
|
+
api_key: config.api_key,
|
63
|
+
sdk_metadata: SDK_METADATA,
|
64
|
+
}),
|
65
|
+
configuration_store.clone(),
|
66
|
+
PollerThreadConfig {
|
67
|
+
interval: poll_interval,
|
68
|
+
jitter: config.poll_jitter,
|
69
|
+
},
|
70
|
+
)
|
71
|
+
.expect("should be able to start poller thread"),
|
72
|
+
)
|
73
|
+
} else {
|
74
|
+
None
|
47
75
|
};
|
48
76
|
|
49
|
-
let poller_thread = PollerThread::start(
|
50
|
-
ConfigurationFetcher::new(ConfigurationFetcherConfig {
|
51
|
-
base_url: config.base_url,
|
52
|
-
api_key: config.api_key,
|
53
|
-
sdk_metadata: sdk_metadata.clone(),
|
54
|
-
}),
|
55
|
-
configuration_store.clone(),
|
56
|
-
)
|
57
|
-
.expect("should be able to start poller thread");
|
58
|
-
|
59
77
|
let evaluator = Evaluator::new(EvaluatorConfig {
|
60
|
-
configuration_store,
|
61
|
-
sdk_metadata,
|
78
|
+
configuration_store: configuration_store.clone(),
|
79
|
+
sdk_metadata: SDK_METADATA,
|
62
80
|
});
|
63
81
|
|
64
82
|
Client {
|
83
|
+
configuration_store,
|
65
84
|
evaluator,
|
66
|
-
poller_thread: RefCell::new(
|
85
|
+
poller_thread: RefCell::new(poller_thread),
|
67
86
|
}
|
68
87
|
}
|
69
88
|
|
@@ -81,8 +100,8 @@ impl Client {
|
|
81
100
|
.evaluator
|
82
101
|
.get_assignment(
|
83
102
|
&flag_key,
|
84
|
-
&subject_key,
|
85
|
-
&subject_attributes,
|
103
|
+
&subject_key.into(),
|
104
|
+
&Arc::new(subject_attributes),
|
86
105
|
Some(expected_type),
|
87
106
|
)
|
88
107
|
// TODO: maybe expose possible errors individually.
|
@@ -103,8 +122,8 @@ impl Client {
|
|
103
122
|
|
104
123
|
let result = self.evaluator.get_assignment_details(
|
105
124
|
&flag_key,
|
106
|
-
&subject_key,
|
107
|
-
&subject_attributes,
|
125
|
+
&subject_key.into(),
|
126
|
+
&Arc::new(subject_attributes),
|
108
127
|
Some(expected_type),
|
109
128
|
);
|
110
129
|
|
@@ -132,10 +151,10 @@ impl Client {
|
|
132
151
|
|
133
152
|
let result = self.evaluator.get_bandit_action(
|
134
153
|
&flag_key,
|
135
|
-
&subject_key,
|
154
|
+
&subject_key.into(),
|
136
155
|
&subject_attributes,
|
137
156
|
&actions,
|
138
|
-
&default_variation,
|
157
|
+
&default_variation.into(),
|
139
158
|
);
|
140
159
|
|
141
160
|
serde_magnus::serialize(&result)
|
@@ -162,15 +181,26 @@ impl Client {
|
|
162
181
|
|
163
182
|
let result = self.evaluator.get_bandit_action_details(
|
164
183
|
&flag_key,
|
165
|
-
&subject_key,
|
184
|
+
&subject_key.into(),
|
166
185
|
&subject_attributes,
|
167
186
|
&actions,
|
168
|
-
&default_variation,
|
187
|
+
&default_variation.into(),
|
169
188
|
);
|
170
189
|
|
171
190
|
serde_magnus::serialize(&result)
|
172
191
|
}
|
173
192
|
|
193
|
+
pub fn get_configuration(&self) -> Option<Configuration> {
|
194
|
+
self.configuration_store
|
195
|
+
.get_configuration()
|
196
|
+
.map(|it| it.into())
|
197
|
+
}
|
198
|
+
|
199
|
+
pub fn set_configuration(&self, configuration: &Configuration) {
|
200
|
+
self.configuration_store
|
201
|
+
.set_configuration(configuration.clone().into())
|
202
|
+
}
|
203
|
+
|
174
204
|
pub fn shutdown(&self) {
|
175
205
|
if let Some(t) = self.poller_thread.take() {
|
176
206
|
let _ = t.shutdown();
|
@@ -0,0 +1,113 @@
|
|
1
|
+
use std::sync::Arc;
|
2
|
+
|
3
|
+
use magnus::{function, method, prelude::*, scan_args::get_kwargs, Error, RHash, RString, Ruby};
|
4
|
+
|
5
|
+
use eppo_core::{ufc::UniversalFlagConfig, Configuration as CoreConfiguration};
|
6
|
+
|
7
|
+
use crate::{gc_lock::GcLock, SDK_METADATA};
|
8
|
+
|
9
|
+
pub(crate) fn init(ruby: &Ruby) -> Result<(), Error> {
|
10
|
+
let eppo_client = ruby.define_module("EppoClient")?;
|
11
|
+
|
12
|
+
let configuration = eppo_client.define_class("Configuration", magnus::class::object())?;
|
13
|
+
configuration.define_singleton_method("new", function!(Configuration::new, 1))?;
|
14
|
+
configuration.define_method(
|
15
|
+
"flags_configuration",
|
16
|
+
method!(Configuration::flags_configuration, 0),
|
17
|
+
)?;
|
18
|
+
configuration.define_method(
|
19
|
+
"bandits_configuration",
|
20
|
+
method!(Configuration::bandits_configuration, 0),
|
21
|
+
)?;
|
22
|
+
|
23
|
+
Ok(())
|
24
|
+
}
|
25
|
+
|
26
|
+
#[derive(Debug, Clone)]
|
27
|
+
#[magnus::wrap(class = "EppoClient::Configuration", free_immediately)]
|
28
|
+
pub struct Configuration {
|
29
|
+
inner: Arc<CoreConfiguration>,
|
30
|
+
}
|
31
|
+
|
32
|
+
impl Configuration {
|
33
|
+
fn new(ruby: &Ruby, kw: RHash) -> Result<Configuration, Error> {
|
34
|
+
let args = get_kwargs(kw, &["flags_configuration"], &["bandits_configuration"])?;
|
35
|
+
let (flags_configuration,): (RString,) = args.required;
|
36
|
+
let (bandits_configuration,): (Option<Option<RString>>,) = args.optional;
|
37
|
+
let rest: RHash = args.splat;
|
38
|
+
if !rest.is_empty() {
|
39
|
+
return Err(Error::new(
|
40
|
+
ruby.exception_arg_error(),
|
41
|
+
format!("unexpected keyword arguments: {:?}", rest),
|
42
|
+
));
|
43
|
+
}
|
44
|
+
|
45
|
+
let inner = {
|
46
|
+
let _gc_lock = GcLock::new(ruby);
|
47
|
+
|
48
|
+
Arc::new(CoreConfiguration::from_server_response(
|
49
|
+
UniversalFlagConfig::from_json(
|
50
|
+
SDK_METADATA,
|
51
|
+
unsafe {
|
52
|
+
// SAFETY: we have disabled GC, so the memory can't be modified concurrently.
|
53
|
+
flags_configuration.as_slice()
|
54
|
+
}
|
55
|
+
.to_vec(),
|
56
|
+
)
|
57
|
+
.map_err(|err| {
|
58
|
+
Error::new(
|
59
|
+
ruby.exception_arg_error(),
|
60
|
+
format!("failed to parse flags_configuration: {err:?}"),
|
61
|
+
)
|
62
|
+
})?,
|
63
|
+
bandits_configuration
|
64
|
+
.flatten()
|
65
|
+
.map(|bandits| {
|
66
|
+
serde_json::from_slice(unsafe {
|
67
|
+
// SAFETY: we have disabled GC, so the memory can't be modified concurrently.
|
68
|
+
bandits.as_slice()
|
69
|
+
})
|
70
|
+
})
|
71
|
+
.transpose()
|
72
|
+
.map_err(|err| {
|
73
|
+
Error::new(
|
74
|
+
ruby.exception_arg_error(),
|
75
|
+
format!("failed to parse bandits_configuration: {err:?}"),
|
76
|
+
)
|
77
|
+
})?,
|
78
|
+
))
|
79
|
+
};
|
80
|
+
|
81
|
+
Ok(Configuration { inner })
|
82
|
+
}
|
83
|
+
|
84
|
+
fn flags_configuration(ruby: &Ruby, rb_self: &Self) -> Result<RString, Error> {
|
85
|
+
Ok(ruby.str_from_slice(rb_self.inner.flags.to_json()))
|
86
|
+
}
|
87
|
+
|
88
|
+
fn bandits_configuration(ruby: &Ruby, rb_self: &Self) -> Result<Option<RString>, Error> {
|
89
|
+
let Some(bandits) = &rb_self.inner.bandits else {
|
90
|
+
return Ok(None)
|
91
|
+
};
|
92
|
+
let vec = serde_json::to_vec(bandits).map_err(|err| {
|
93
|
+
// this should never happen
|
94
|
+
Error::new(
|
95
|
+
ruby.exception_runtime_error(),
|
96
|
+
format!("failed to serialize bandits configuration: {err:?}"),
|
97
|
+
)
|
98
|
+
})?;
|
99
|
+
Ok(Some(ruby.str_from_slice(&vec)))
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
impl From<Arc<CoreConfiguration>> for Configuration {
|
104
|
+
fn from(inner: Arc<CoreConfiguration>) -> Configuration {
|
105
|
+
Configuration { inner }
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
impl From<Configuration> for Arc<CoreConfiguration> {
|
110
|
+
fn from(value: Configuration) -> Arc<CoreConfiguration> {
|
111
|
+
value.inner
|
112
|
+
}
|
113
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
use magnus::Ruby;
|
2
|
+
|
3
|
+
pub struct GcLock<'a> {
|
4
|
+
ruby: &'a Ruby,
|
5
|
+
/// Holds `true` if GC was already disabled before acquiring the lock (so it doesn't need to be
|
6
|
+
/// re-enabled).
|
7
|
+
gc_was_disabled: bool,
|
8
|
+
}
|
9
|
+
|
10
|
+
impl<'a> GcLock<'a> {
|
11
|
+
pub fn new(ruby: &'a Ruby) -> GcLock<'a> {
|
12
|
+
GcLock {
|
13
|
+
ruby,
|
14
|
+
gc_was_disabled: ruby.gc_disable(),
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
impl<'a> Drop for GcLock<'a> {
|
20
|
+
fn drop(&mut self) {
|
21
|
+
if !self.gc_was_disabled {
|
22
|
+
self.ruby.gc_enable();
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
data/ext/eppo_client/src/lib.rs
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
mod client;
|
2
|
+
mod configuration;
|
3
|
+
mod gc_lock;
|
2
4
|
|
5
|
+
use eppo_core::SdkMetadata;
|
3
6
|
use magnus::{function, method, prelude::*, Error, Object, Ruby};
|
4
7
|
|
5
8
|
use crate::client::Client;
|
6
9
|
|
10
|
+
pub(crate) const SDK_METADATA: SdkMetadata = SdkMetadata {
|
11
|
+
name: "ruby",
|
12
|
+
version: env!("CARGO_PKG_VERSION"),
|
13
|
+
};
|
14
|
+
|
7
15
|
#[magnus::init]
|
8
16
|
fn init(ruby: &Ruby) -> Result<(), Error> {
|
9
|
-
env_logger::Builder::from_env(env_logger::Env::new().default_filter_or("eppo")).init();
|
17
|
+
env_logger::Builder::from_env(env_logger::Env::new().default_filter_or("eppo=debug")).init();
|
10
18
|
|
11
19
|
let eppo_client = ruby.define_module("EppoClient")?;
|
12
20
|
let core = eppo_client.define_module("Core")?;
|
@@ -23,12 +31,24 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
|
|
23
31
|
"get_bandit_action_details",
|
24
32
|
method!(Client::get_bandit_action_details, 5),
|
25
33
|
)?;
|
34
|
+
core_client.define_method("configuration", method!(Client::get_configuration, 0))?;
|
35
|
+
core_client.define_method("configuration=", method!(Client::set_configuration, 1))?;
|
26
36
|
core_client.define_method("shutdown", method!(Client::shutdown, 0))?;
|
27
37
|
|
28
38
|
core.const_set(
|
29
39
|
"DEFAULT_BASE_URL",
|
30
40
|
eppo_core::configuration_fetcher::DEFAULT_BASE_URL,
|
31
41
|
)?;
|
42
|
+
core.const_set(
|
43
|
+
"DEFAULT_POLL_INTERVAL_SECONDS",
|
44
|
+
eppo_core::poller_thread::PollerThreadConfig::DEFAULT_POLL_INTERVAL.as_secs(),
|
45
|
+
)?;
|
46
|
+
core.const_set(
|
47
|
+
"DEFAULT_POLL_JITTER_SECONDS",
|
48
|
+
eppo_core::poller_thread::PollerThreadConfig::DEFAULT_POLL_JITTER.as_secs(),
|
49
|
+
)?;
|
50
|
+
|
51
|
+
configuration::init(ruby)?;
|
32
52
|
|
33
53
|
Ok(())
|
34
54
|
}
|
data/lib/eppo_client/client.rb
CHANGED
@@ -24,6 +24,14 @@ module EppoClient
|
|
24
24
|
@core = EppoClient::Core::Client.new(config)
|
25
25
|
end
|
26
26
|
|
27
|
+
def configuration
|
28
|
+
@core.configuration
|
29
|
+
end
|
30
|
+
|
31
|
+
def configuration=(configuration)
|
32
|
+
@core.configuration = configuration
|
33
|
+
end
|
34
|
+
|
27
35
|
def shutdown
|
28
36
|
@core.shutdown
|
29
37
|
end
|
data/lib/eppo_client/config.rb
CHANGED
@@ -6,12 +6,14 @@ require_relative "assignment_logger"
|
|
6
6
|
module EppoClient
|
7
7
|
# The class for configuring the Eppo client singleton
|
8
8
|
class Config
|
9
|
-
attr_reader :api_key, :assignment_logger, :base_url
|
9
|
+
attr_reader :api_key, :assignment_logger, :base_url, :poll_interval_seconds, :poll_jitter_seconds
|
10
10
|
|
11
|
-
def initialize(api_key, assignment_logger: AssignmentLogger.new, base_url: EppoClient::Core::DEFAULT_BASE_URL)
|
11
|
+
def initialize(api_key, assignment_logger: AssignmentLogger.new, base_url: EppoClient::Core::DEFAULT_BASE_URL, poll_interval_seconds: EppoClient::Core::DEFAULT_POLL_INTERVAL_SECONDS, poll_jitter_seconds: EppoClient::Core::DEFAULT_POLL_JITTER_SECONDS, initial_configuration: nil)
|
12
12
|
@api_key = api_key
|
13
13
|
@assignment_logger = assignment_logger
|
14
14
|
@base_url = base_url
|
15
|
+
@poll_interval_seconds = poll_interval_seconds
|
16
|
+
@poll_jitter_seconds = poll_jitter_seconds
|
15
17
|
end
|
16
18
|
|
17
19
|
def validate
|
data/lib/eppo_client/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eppo-server-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eppo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -31,6 +31,8 @@ files:
|
|
31
31
|
- ext/eppo_client/build.rs
|
32
32
|
- ext/eppo_client/extconf.rb
|
33
33
|
- ext/eppo_client/src/client.rs
|
34
|
+
- ext/eppo_client/src/configuration.rs
|
35
|
+
- ext/eppo_client/src/gc_lock.rs
|
34
36
|
- ext/eppo_client/src/lib.rs
|
35
37
|
- lib/eppo_client.rb
|
36
38
|
- lib/eppo_client/assignment_logger.rb
|