eppo-server-sdk 3.4.2 → 3.4.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec619c7cb4e7d38b3781bdb18b59786801cd1655733e071627ed4f85ba687a77
4
- data.tar.gz: d42205f8c88c4c841cbac828b51aa5e68bd34cec4404caf10834beb3065bc52e
3
+ metadata.gz: 71322e0193925c1f98f447eafaba1212a92d09595a68dce2ac6a3570af76712a
4
+ data.tar.gz: deb228f64ef74d43b487659e54567d5a9e30cd008c2ab29f0785ed55c6c8b070
5
5
  SHA512:
6
- metadata.gz: 6e5cc805e3f3d2d02143915d77137b427ae610fa99b756a71d68fe964898e2353edcb6ee577227f23d53a31c966611a69a4d474a73acf73a2f3b2ede0980ec18
7
- data.tar.gz: 7d30bca34cc3afcc3232ca3cec995bc0d94d45002cd34326e26034429fdcfb0cecb1e67d1c43ef06f02d8427b7980c0e5533245b05ebb18eea8f032a3874566d
6
+ metadata.gz: c580533bea972b2d5330318ce698c019c849ed3686c40ce54c08281e27ec85d31b815ea27dd2395bd1835161f3a023f2f614bc42230f8dc37f4cfe58c1ba681d
7
+ data.tar.gz: 3a48b9ee7312019db3cd6d491668c10bf87c7e570eb6f5551ef21802562ae80a9a65def2abb101e1010f3a4843acfc5c35ef80ccefe76edcf6f90e5740256896
data/Cargo.lock CHANGED
@@ -285,18 +285,18 @@ dependencies = [
285
285
 
286
286
  [[package]]
287
287
  name = "derive_more"
288
- version = "1.0.0"
288
+ version = "2.0.1"
289
289
  source = "registry+https://github.com/rust-lang/crates.io-index"
290
- checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
290
+ checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
291
291
  dependencies = [
292
292
  "derive_more-impl",
293
293
  ]
294
294
 
295
295
  [[package]]
296
296
  name = "derive_more-impl"
297
- version = "1.0.0"
297
+ version = "2.0.1"
298
298
  source = "registry+https://github.com/rust-lang/crates.io-index"
299
- checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
299
+ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
300
300
  dependencies = [
301
301
  "proc-macro2",
302
302
  "quote",
@@ -354,7 +354,7 @@ dependencies = [
354
354
 
355
355
  [[package]]
356
356
  name = "eppo_client"
357
- version = "3.4.2"
357
+ version = "3.4.3"
358
358
  dependencies = [
359
359
  "env_logger",
360
360
  "eppo_core",
@@ -368,13 +368,14 @@ dependencies = [
368
368
 
369
369
  [[package]]
370
370
  name = "eppo_core"
371
- version = "7.0.2"
371
+ version = "8.0.0"
372
372
  source = "registry+https://github.com/rust-lang/crates.io-index"
373
- checksum = "3955a514eecc18087e625d42bf4e0d62406a85f130b079ce53b601188953b759"
373
+ checksum = "c6a83f5d76e9289ead0d6ed15350e46d3a0c8b9bd1e212ff5a0762882fd79ca1"
374
374
  dependencies = [
375
375
  "base64",
376
376
  "chrono",
377
377
  "derive_more",
378
+ "exponential-backoff",
378
379
  "faststr",
379
380
  "log",
380
381
  "magnus",
@@ -390,6 +391,7 @@ dependencies = [
390
391
  "serde_with",
391
392
  "thiserror",
392
393
  "tokio",
394
+ "tokio-util",
393
395
  "url",
394
396
  "uuid",
395
397
  ]
@@ -420,6 +422,15 @@ dependencies = [
420
422
  "windows-sys 0.59.0",
421
423
  ]
422
424
 
425
+ [[package]]
426
+ name = "exponential-backoff"
427
+ version = "2.0.0"
428
+ source = "registry+https://github.com/rust-lang/crates.io-index"
429
+ checksum = "6ffb309d235a642598183aeda8925e871e85dd5a433c2c877e69ff0a960f4c02"
430
+ dependencies = [
431
+ "fastrand",
432
+ ]
433
+
423
434
  [[package]]
424
435
  name = "fastrand"
425
436
  version = "2.2.0"
@@ -482,6 +493,17 @@ version = "0.3.31"
482
493
  source = "registry+https://github.com/rust-lang/crates.io-index"
483
494
  checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
484
495
 
496
+ [[package]]
497
+ name = "futures-macro"
498
+ version = "0.3.31"
499
+ source = "registry+https://github.com/rust-lang/crates.io-index"
500
+ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
501
+ dependencies = [
502
+ "proc-macro2",
503
+ "quote",
504
+ "syn",
505
+ ]
506
+
485
507
  [[package]]
486
508
  name = "futures-sink"
487
509
  version = "0.3.31"
@@ -501,9 +523,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
501
523
  checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
502
524
  dependencies = [
503
525
  "futures-core",
526
+ "futures-macro",
504
527
  "futures-task",
505
528
  "pin-project-lite",
506
529
  "pin-utils",
530
+ "slab",
507
531
  ]
508
532
 
509
533
  [[package]]
@@ -514,7 +538,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
514
538
  dependencies = [
515
539
  "cfg-if",
516
540
  "libc",
517
- "wasi",
541
+ "wasi 0.11.0+wasi-snapshot-preview1",
542
+ ]
543
+
544
+ [[package]]
545
+ name = "getrandom"
546
+ version = "0.3.1"
547
+ source = "registry+https://github.com/rust-lang/crates.io-index"
548
+ checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
549
+ dependencies = [
550
+ "cfg-if",
551
+ "libc",
552
+ "wasi 0.13.3+wasi-0.2.2",
553
+ "windows-targets",
518
554
  ]
519
555
 
520
556
  [[package]]
@@ -548,6 +584,12 @@ dependencies = [
548
584
  "tracing",
549
585
  ]
550
586
 
587
+ [[package]]
588
+ name = "hashbrown"
589
+ version = "0.14.5"
590
+ source = "registry+https://github.com/rust-lang/crates.io-index"
591
+ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
592
+
551
593
  [[package]]
552
594
  name = "hashbrown"
553
595
  version = "0.15.2"
@@ -848,19 +890,19 @@ dependencies = [
848
890
 
849
891
  [[package]]
850
892
  name = "indexmap"
851
- version = "2.7.0"
893
+ version = "2.7.1"
852
894
  source = "registry+https://github.com/rust-lang/crates.io-index"
853
- checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
895
+ checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
854
896
  dependencies = [
855
897
  "equivalent",
856
- "hashbrown",
898
+ "hashbrown 0.15.2",
857
899
  ]
858
900
 
859
901
  [[package]]
860
902
  name = "ipnet"
861
- version = "2.10.1"
903
+ version = "2.11.0"
862
904
  source = "registry+https://github.com/rust-lang/crates.io-index"
863
- checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
905
+ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
864
906
 
865
907
  [[package]]
866
908
  name = "is_terminal_polyfill"
@@ -1006,7 +1048,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1006
1048
  checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
1007
1049
  dependencies = [
1008
1050
  "libc",
1009
- "wasi",
1051
+ "wasi 0.11.0+wasi-snapshot-preview1",
1010
1052
  "windows-sys 0.52.0",
1011
1053
  ]
1012
1054
 
@@ -1157,7 +1199,7 @@ version = "0.2.20"
1157
1199
  source = "registry+https://github.com/rust-lang/crates.io-index"
1158
1200
  checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
1159
1201
  dependencies = [
1160
- "zerocopy",
1202
+ "zerocopy 0.7.35",
1161
1203
  ]
1162
1204
 
1163
1205
  [[package]]
@@ -1180,20 +1222,20 @@ dependencies = [
1180
1222
 
1181
1223
  [[package]]
1182
1224
  name = "rand"
1183
- version = "0.8.5"
1225
+ version = "0.9.0"
1184
1226
  source = "registry+https://github.com/rust-lang/crates.io-index"
1185
- checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1227
+ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
1186
1228
  dependencies = [
1187
- "libc",
1188
1229
  "rand_chacha",
1189
1230
  "rand_core",
1231
+ "zerocopy 0.8.15",
1190
1232
  ]
1191
1233
 
1192
1234
  [[package]]
1193
1235
  name = "rand_chacha"
1194
- version = "0.3.1"
1236
+ version = "0.9.0"
1195
1237
  source = "registry+https://github.com/rust-lang/crates.io-index"
1196
- checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1238
+ checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
1197
1239
  dependencies = [
1198
1240
  "ppv-lite86",
1199
1241
  "rand_core",
@@ -1201,11 +1243,12 @@ dependencies = [
1201
1243
 
1202
1244
  [[package]]
1203
1245
  name = "rand_core"
1204
- version = "0.6.4"
1246
+ version = "0.9.0"
1205
1247
  source = "registry+https://github.com/rust-lang/crates.io-index"
1206
- checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1248
+ checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
1207
1249
  dependencies = [
1208
- "getrandom",
1250
+ "getrandom 0.3.1",
1251
+ "zerocopy 0.8.15",
1209
1252
  ]
1210
1253
 
1211
1254
  [[package]]
@@ -1318,7 +1361,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
1318
1361
  dependencies = [
1319
1362
  "cc",
1320
1363
  "cfg-if",
1321
- "getrandom",
1364
+ "getrandom 0.2.15",
1322
1365
  "libc",
1323
1366
  "spin",
1324
1367
  "untrusted",
@@ -1847,24 +1890,25 @@ dependencies = [
1847
1890
 
1848
1891
  [[package]]
1849
1892
  name = "tokio-rustls"
1850
- version = "0.26.0"
1893
+ version = "0.26.1"
1851
1894
  source = "registry+https://github.com/rust-lang/crates.io-index"
1852
- checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
1895
+ checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
1853
1896
  dependencies = [
1854
1897
  "rustls",
1855
- "rustls-pki-types",
1856
1898
  "tokio",
1857
1899
  ]
1858
1900
 
1859
1901
  [[package]]
1860
1902
  name = "tokio-util"
1861
- version = "0.7.12"
1903
+ version = "0.7.13"
1862
1904
  source = "registry+https://github.com/rust-lang/crates.io-index"
1863
- checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
1905
+ checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
1864
1906
  dependencies = [
1865
1907
  "bytes",
1866
1908
  "futures-core",
1867
1909
  "futures-sink",
1910
+ "futures-util",
1911
+ "hashbrown 0.14.5",
1868
1912
  "pin-project-lite",
1869
1913
  "tokio",
1870
1914
  ]
@@ -1949,11 +1993,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
1949
1993
 
1950
1994
  [[package]]
1951
1995
  name = "uuid"
1952
- version = "1.11.1"
1996
+ version = "1.12.1"
1953
1997
  source = "registry+https://github.com/rust-lang/crates.io-index"
1954
- checksum = "b913a3b5fe84142e269d63cc62b64319ccaf89b748fc31fe025177f767a756c4"
1998
+ checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
1955
1999
  dependencies = [
1956
- "getrandom",
2000
+ "getrandom 0.2.15",
1957
2001
  "serde",
1958
2002
  ]
1959
2003
 
@@ -2014,6 +2058,15 @@ version = "0.11.0+wasi-snapshot-preview1"
2014
2058
  source = "registry+https://github.com/rust-lang/crates.io-index"
2015
2059
  checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2016
2060
 
2061
+ [[package]]
2062
+ name = "wasi"
2063
+ version = "0.13.3+wasi-0.2.2"
2064
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2065
+ checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
2066
+ dependencies = [
2067
+ "wit-bindgen-rt",
2068
+ ]
2069
+
2017
2070
  [[package]]
2018
2071
  name = "wasm-bindgen"
2019
2072
  version = "0.2.97"
@@ -2213,6 +2266,15 @@ version = "0.52.6"
2213
2266
  source = "registry+https://github.com/rust-lang/crates.io-index"
2214
2267
  checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2215
2268
 
2269
+ [[package]]
2270
+ name = "wit-bindgen-rt"
2271
+ version = "0.33.0"
2272
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2273
+ checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
2274
+ dependencies = [
2275
+ "bitflags",
2276
+ ]
2277
+
2216
2278
  [[package]]
2217
2279
  name = "write16"
2218
2280
  version = "1.0.0"
@@ -2256,7 +2318,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2256
2318
  checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
2257
2319
  dependencies = [
2258
2320
  "byteorder",
2259
- "zerocopy-derive",
2321
+ "zerocopy-derive 0.7.35",
2322
+ ]
2323
+
2324
+ [[package]]
2325
+ name = "zerocopy"
2326
+ version = "0.8.15"
2327
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2328
+ checksum = "a1e101d4bc320b6f9abb68846837b70e25e380ca2f467ab494bf29fcc435fcc3"
2329
+ dependencies = [
2330
+ "zerocopy-derive 0.8.15",
2260
2331
  ]
2261
2332
 
2262
2333
  [[package]]
@@ -2270,6 +2341,17 @@ dependencies = [
2270
2341
  "syn",
2271
2342
  ]
2272
2343
 
2344
+ [[package]]
2345
+ name = "zerocopy-derive"
2346
+ version = "0.8.15"
2347
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2348
+ checksum = "03a73df1008145cd135b3c780d275c57c3e6ba8324a41bd5e0008fe167c3bc7c"
2349
+ dependencies = [
2350
+ "proc-macro2",
2351
+ "quote",
2352
+ "syn",
2353
+ ]
2354
+
2273
2355
  [[package]]
2274
2356
  name = "zerofrom"
2275
2357
  version = "0.1.5"
@@ -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.2"
4
+ version = "3.4.3"
5
5
  edition = "2021"
6
6
  license = "MIT"
7
7
  publish = false
@@ -12,7 +12,7 @@ crate-type = ["cdylib"]
12
12
 
13
13
  [dependencies]
14
14
  env_logger = { version = "0.11.3", features = ["unstable-kv"] }
15
- eppo_core = { version = "=7.0.2", features = ["vendored", "magnus"] }
15
+ eppo_core = { version = "=8.0.0", features = ["vendored", "magnus", "event_ingestion"] }
16
16
  log = { version = "0.4.21", features = ["kv_serde"] }
17
17
  magnus = { version = "0.6.4" }
18
18
  serde = { version = "1.0.203", features = ["derive"] }
@@ -1,17 +1,20 @@
1
1
  use std::{cell::RefCell, str::FromStr, sync::Arc, time::Duration};
2
2
 
3
+ use crate::{configuration::Configuration, SDK_METADATA};
3
4
  use eppo_core::{
5
+ background::BackgroundThread,
4
6
  configuration_fetcher::{ConfigurationFetcher, ConfigurationFetcherConfig},
7
+ configuration_poller::{
8
+ start_configuration_poller, ConfigurationPoller, ConfigurationPollerConfig,
9
+ },
5
10
  configuration_store::ConfigurationStore,
6
11
  eval::{Evaluator, EvaluatorConfig},
7
- poller_thread::{PollerThread, PollerThreadConfig},
12
+ event_ingestion::{EventIngestion, EventIngestionConfig},
8
13
  ufc::VariationType,
9
- Attributes, ContextAttributes,
14
+ Attributes, ContextAttributes, SdkKey,
10
15
  };
11
16
  use magnus::{error::Result, exception, prelude::*, Error, IntoValue, Ruby, TryConvert, Value};
12
17
 
13
- use crate::{configuration::Configuration, SDK_METADATA};
14
-
15
18
  #[derive(Debug)]
16
19
  #[magnus::wrap(class = "EppoClient::Core::Config", size, free_immediately)]
17
20
  pub struct Config {
@@ -20,17 +23,17 @@ pub struct Config {
20
23
  poll_interval: Option<Duration>,
21
24
  poll_jitter: Duration,
22
25
  log_level: Option<log::LevelFilter>,
26
+ event_ingestion_config: Option<EventIngestionConfig>,
23
27
  }
24
28
 
25
29
  impl TryConvert for Config {
26
30
  // `val` is expected to be of type EppoClient::Config.
27
- fn try_convert(val: magnus::Value) -> Result<Self> {
28
- let api_key = String::try_convert(val.funcall("api_key", ())?)?;
31
+ fn try_convert(val: Value) -> Result<Self> {
32
+ let sdk_key = String::try_convert(val.funcall("api_key", ())?)?;
29
33
  let base_url = String::try_convert(val.funcall("base_url", ())?)?;
30
34
  let poll_interval_seconds =
31
35
  Option::<u64>::try_convert(val.funcall("poll_interval_seconds", ())?)?;
32
36
  let poll_jitter_seconds = u64::try_convert(val.funcall("poll_jitter_seconds", ())?)?;
33
-
34
37
  let log_level = {
35
38
  let s = Option::<String>::try_convert(val.funcall("log_level", ())?)?;
36
39
  s.map(|s| {
@@ -40,12 +43,14 @@ impl TryConvert for Config {
40
43
  .transpose()?
41
44
  };
42
45
 
46
+ let event_ingestion_config = EventIngestionConfig::new(SdkKey::new(sdk_key.clone().into()));
43
47
  Ok(Config {
44
- api_key,
48
+ api_key: sdk_key,
45
49
  base_url,
46
50
  poll_interval: poll_interval_seconds.map(Duration::from_secs),
47
51
  poll_jitter: Duration::from_secs(poll_jitter_seconds),
48
52
  log_level,
53
+ event_ingestion_config,
49
54
  })
50
55
  }
51
56
  }
@@ -54,12 +59,15 @@ impl TryConvert for Config {
54
59
  pub struct Client {
55
60
  configuration_store: Arc<ConfigurationStore>,
56
61
  evaluator: Evaluator,
62
+
57
63
  // Magnus only allows sharing aliased references (&T) through the API, so we need to use RefCell
58
64
  // to get interior mutability.
59
65
  //
60
66
  // This should be safe as Ruby only uses a single OS thread, and `Client` lives in the Ruby
61
67
  // world.
62
- poller_thread: RefCell<Option<PollerThread>>,
68
+ background_thread: RefCell<Option<BackgroundThread>>,
69
+ configuration_poller: Option<ConfigurationPoller>,
70
+ event_ingestion: Option<EventIngestion>,
63
71
  }
64
72
 
65
73
  impl Client {
@@ -83,35 +91,43 @@ impl Client {
83
91
 
84
92
  let configuration_store = Arc::new(ConfigurationStore::new());
85
93
 
86
- let poller_thread = if let Some(poll_interval) = config.poll_interval {
87
- Some(
88
- PollerThread::start_with_config(
89
- ConfigurationFetcher::new(ConfigurationFetcherConfig {
90
- base_url: config.base_url,
91
- api_key: config.api_key,
92
- sdk_metadata: SDK_METADATA,
93
- }),
94
- configuration_store.clone(),
95
- PollerThreadConfig {
96
- interval: poll_interval,
97
- jitter: config.poll_jitter,
98
- },
99
- )
100
- .expect("should be able to start poller thread"),
101
- )
102
- } else {
103
- None
104
- };
105
-
106
94
  let evaluator = Evaluator::new(EvaluatorConfig {
107
95
  configuration_store: configuration_store.clone(),
108
96
  sdk_metadata: SDK_METADATA,
109
97
  });
110
98
 
99
+ let background_thread =
100
+ BackgroundThread::start().expect("should be able to start background thread");
101
+
102
+ let configuration_poller = if let Some(poll_interval) = config.poll_interval {
103
+ let poller = start_configuration_poller(
104
+ background_thread.runtime(),
105
+ ConfigurationFetcher::new(ConfigurationFetcherConfig {
106
+ base_url: config.base_url,
107
+ api_key: config.api_key,
108
+ sdk_metadata: SDK_METADATA,
109
+ }),
110
+ configuration_store.clone(),
111
+ ConfigurationPollerConfig {
112
+ interval: poll_interval,
113
+ jitter: config.poll_jitter,
114
+ },
115
+ );
116
+ Some(poller)
117
+ } else {
118
+ None
119
+ };
120
+
121
+ let event_ingestion = config
122
+ .event_ingestion_config
123
+ .map(|config| config.spawn(background_thread.runtime()));
124
+
111
125
  Client {
112
126
  configuration_store,
113
127
  evaluator,
114
- poller_thread: RefCell::new(poller_thread),
128
+ background_thread: RefCell::new(Some(background_thread)),
129
+ configuration_poller,
130
+ event_ingestion,
115
131
  }
116
132
  }
117
133
 
@@ -206,7 +222,7 @@ impl Client {
206
222
  .map_err(|err| {
207
223
  Error::new(
208
224
  exception::runtime_error(),
209
- format!("enexpected value for subject_attributes: {err}"),
225
+ format!("Unexpected value for subject_attributes: {err}"),
210
226
  )
211
227
  })?;
212
228
  let actions = serde_magnus::deserialize(actions)?;
@@ -234,8 +250,26 @@ impl Client {
234
250
  }
235
251
 
236
252
  pub fn shutdown(&self) {
237
- if let Some(t) = self.poller_thread.take() {
238
- let _ = t.shutdown();
253
+ if let Some(thread) = self.background_thread.take() {
254
+ thread.graceful_shutdown();
239
255
  }
240
256
  }
257
+
258
+ pub fn track(&self, event_type: String, payload: Value) -> Result<()> {
259
+ let Some(event_ingestion) = &self.event_ingestion else {
260
+ // Event ingestion is disabled, do nothing.
261
+ return Ok(());
262
+ };
263
+
264
+ let payload: serde_json::Value = serde_magnus::deserialize(payload).map_err(|err| {
265
+ Error::new(
266
+ exception::runtime_error(),
267
+ format!("Unexpected value for payload: {err}"),
268
+ )
269
+ })?;
270
+
271
+ event_ingestion.track(event_type, payload);
272
+
273
+ Ok(())
274
+ }
241
275
  }
@@ -81,22 +81,20 @@ impl Configuration {
81
81
  Ok(Configuration { inner })
82
82
  }
83
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()))
84
+ fn flags_configuration(ruby: &Ruby, rb_self: &Self) -> Result<Option<RString>, Error> {
85
+ let result = rb_self
86
+ .inner
87
+ .get_flags_configuration()
88
+ .map(|s| ruby.str_from_slice(s.as_ref()));
89
+ Ok(result)
86
90
  }
87
91
 
88
92
  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)))
93
+ let result = rb_self
94
+ .inner
95
+ .get_bandits_configuration()
96
+ .map(|s| ruby.str_from_slice(s.as_ref()));
97
+ Ok(result)
100
98
  }
101
99
  }
102
100
 
@@ -16,7 +16,6 @@ pub(crate) const SDK_METADATA: SdkMetadata = SdkMetadata {
16
16
  fn init(ruby: &Ruby) -> Result<(), Error> {
17
17
  let eppo_client = ruby.define_module("EppoClient")?;
18
18
  let core = eppo_client.define_module("Core")?;
19
-
20
19
  let core_client = core.define_class("Client", magnus::class::object())?;
21
20
  core_client.define_singleton_method("new", function!(Client::new, 1))?;
22
21
  core_client.define_method("get_assignment", method!(Client::get_assignment, 4))?;
@@ -29,6 +28,7 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
29
28
  "get_bandit_action_details",
30
29
  method!(Client::get_bandit_action_details, 5),
31
30
  )?;
31
+ core_client.define_method("track", method!(Client::track, 2))?;
32
32
  core_client.define_method("configuration", method!(Client::get_configuration, 0))?;
33
33
  core_client.define_method("configuration=", method!(Client::set_configuration, 1))?;
34
34
  core_client.define_method("shutdown", method!(Client::shutdown, 0))?;
@@ -39,11 +39,11 @@ fn init(ruby: &Ruby) -> Result<(), Error> {
39
39
  )?;
40
40
  core.const_set(
41
41
  "DEFAULT_POLL_INTERVAL_SECONDS",
42
- eppo_core::poller_thread::PollerThreadConfig::DEFAULT_POLL_INTERVAL.as_secs(),
42
+ eppo_core::configuration_poller::ConfigurationPollerConfig::DEFAULT_POLL_INTERVAL.as_secs(),
43
43
  )?;
44
44
  core.const_set(
45
45
  "DEFAULT_POLL_JITTER_SECONDS",
46
- eppo_core::poller_thread::PollerThreadConfig::DEFAULT_POLL_JITTER.as_secs(),
46
+ eppo_core::configuration_poller::ConfigurationPollerConfig::DEFAULT_POLL_JITTER.as_secs(),
47
47
  )?;
48
48
 
49
49
  configuration::init(ruby)?;
@@ -43,6 +43,12 @@ module EppoClient
43
43
  @core.shutdown
44
44
  end
45
45
 
46
+ # Unstable
47
+ # Enqueues an arbitrary event. Events must have a type and a payload
48
+ def unstable_track(event_type, payload)
49
+ @core.track(event_type, payload)
50
+ end
51
+
46
52
  def get_string_assignment(flag_key, subject_key, subject_attributes, default_value)
47
53
  get_assignment_inner(flag_key, subject_key, subject_attributes, "STRING", default_value)
48
54
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # TODO: this version and ext/eppo_client/Cargo.toml should be in sync
4
4
  module EppoClient
5
- VERSION = "3.4.2"
5
+ VERSION = "3.4.3"
6
6
  end
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.2
4
+ version: 3.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eppo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-17 00:00:00.000000000 Z
11
+ date: 2025-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_sys