eppo-server-sdk 3.1.2 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e157a64d8d72757a3bd049d7e40db5589fb7b16d6ff466ea4a1015dbb54fa066
4
- data.tar.gz: 9a4d5cd6edec77d1b8bf8103debe2b096816b6e9957a1c2308747a5182b5a703
3
+ metadata.gz: 58a6e5ef2e00c9c830661f2571eab4f6817e2ceaf40de3dd541b7f2421fb24c0
4
+ data.tar.gz: 8616534de1a08cd7c9d02570da27b15c64e4df0e2c805301bd3f4e54f1b6d3d0
5
5
  SHA512:
6
- metadata.gz: 1b98a6ee8aefd1b833f83ddae8141f42798f825a30f0a54d257f390aa24efc9d8e8a2f1c5b9ff1542db9c11700b7d5fac513c0fa1632aca2f5d22b1eb1a4a9b2
7
- data.tar.gz: abc686a5a7e46bf85ba655157de3b7ae9b9367e53603d962741d52edac3f42da1e24301a67145b6719663583a89083dbe0e5df757ebf0a6decc8a570f8f64edf
6
+ metadata.gz: 23fe167a77c13f00137469b6bf078cb27e907dc1a5b4d18cc6f9bcfbda0a60f9620425d92eca98f3a4d2034796cd5b7f09bf9d08f6a61e0c9fa66b14c5f3730b
7
+ data.tar.gz: 9722bfdd197f648bcfd82b9f93f232c834d8c17a43b73b221bcfe47927b2dc2ed81cf3a95ad856b6497479861f82093b7127e9bbaa814d39bca48c2fd6662977
data/Cargo.lock CHANGED
@@ -304,7 +304,7 @@ dependencies = [
304
304
 
305
305
  [[package]]
306
306
  name = "eppo_client"
307
- version = "3.1.2"
307
+ version = "3.2.2"
308
308
  dependencies = [
309
309
  "env_logger",
310
310
  "eppo_core",
@@ -312,14 +312,15 @@ 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 = "4.0.0"
321
+ version = "4.1.0"
321
322
  source = "registry+https://github.com/rust-lang/crates.io-index"
322
- checksum = "b071fed21065318dcd6a91a443bd9f6b39796d727297b03d092e2e8dc9e02414"
323
+ checksum = "626df025f5b474b42ead14953310e31e81e4b88ce52a993573bf87bc9def12d4"
323
324
  dependencies = [
324
325
  "chrono",
325
326
  "derive_more",
@@ -906,6 +907,15 @@ version = "0.1.5"
906
907
  source = "registry+https://github.com/rust-lang/crates.io-index"
907
908
  checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
908
909
 
910
+ [[package]]
911
+ name = "openssl-src"
912
+ version = "300.3.1+3.3.1"
913
+ source = "registry+https://github.com/rust-lang/crates.io-index"
914
+ checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91"
915
+ dependencies = [
916
+ "cc",
917
+ ]
918
+
909
919
  [[package]]
910
920
  name = "openssl-sys"
911
921
  version = "0.9.103"
@@ -914,6 +924,7 @@ checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
914
924
  dependencies = [
915
925
  "cc",
916
926
  "libc",
927
+ "openssl-src",
917
928
  "pkg-config",
918
929
  "vcpkg",
919
930
  ]
@@ -1021,18 +1032,18 @@ dependencies = [
1021
1032
 
1022
1033
  [[package]]
1023
1034
  name = "rb-sys"
1024
- version = "0.9.100"
1035
+ version = "0.9.102"
1025
1036
  source = "registry+https://github.com/rust-lang/crates.io-index"
1026
- checksum = "87f2ba20be84b32fad6b0ce397764bcdd0f2dca4431cf7035f6a6721e5747565"
1037
+ checksum = "df4dec4b1d304c3b308a2cd86b1216ea45dd4361f4e9fa056f108332d0a450c1"
1027
1038
  dependencies = [
1028
1039
  "rb-sys-build",
1029
1040
  ]
1030
1041
 
1031
1042
  [[package]]
1032
1043
  name = "rb-sys-build"
1033
- version = "0.9.100"
1044
+ version = "0.9.102"
1034
1045
  source = "registry+https://github.com/rust-lang/crates.io-index"
1035
- checksum = "7ecae2bdcb118ee721d9a3929f89e8578237fade298dfcf8c928609aa88abc48"
1046
+ checksum = "1d71de3e29d174b8fb17b5d4470f27d7aa2605f8a9d05fda0d3aeff30e05a570"
1036
1047
  dependencies = [
1037
1048
  "bindgen",
1038
1049
  "lazy_static",
@@ -1295,9 +1306,9 @@ dependencies = [
1295
1306
 
1296
1307
  [[package]]
1297
1308
  name = "serde_json"
1298
- version = "1.0.124"
1309
+ version = "1.0.128"
1299
1310
  source = "registry+https://github.com/rust-lang/crates.io-index"
1300
- checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
1311
+ checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
1301
1312
  dependencies = [
1302
1313
  "itoa",
1303
1314
  "memchr",
data/Rakefile CHANGED
@@ -1,18 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
4
  require_relative 'lib/eppo_client/version'
6
5
 
7
6
  GEM_NAME = 'eppo-server-sdk'
8
7
  GEM_VERSION = EppoClient::VERSION
9
8
 
10
- RSpec::Core::RakeTask.new(:spec)
11
-
12
- require "rubocop/rake_task"
13
-
14
- RuboCop::RakeTask.new
15
-
16
9
  require "rb_sys/extensiontask"
17
10
 
18
11
  task default: :build
@@ -21,6 +14,8 @@ GEMSPEC = Gem::Specification.load("eppo-server-sdk.gemspec")
21
14
 
22
15
  RbSys::ExtensionTask.new("eppo_client", GEMSPEC) do |ext|
23
16
  ext.lib_dir = "lib/eppo_client"
17
+
18
+ ext.cross_compile = true
24
19
  end
25
20
 
26
21
  task build: :compile do
@@ -43,11 +38,5 @@ task :clean do
43
38
  system 'rm *.gem'
44
39
  end
45
40
 
46
- RSpec::Core::RakeTask.new(:test) do |task|
47
- root_dir = Rake.application.original_dir
48
- task.pattern = "#{root_dir}/spec/*_spec.rb"
49
- task.verbose = false
50
- end
51
-
52
41
  task test: :devinstall
53
42
  task test_refreshed_data: [:devinstall, 'test-data']
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+
3
+ ## From:
4
+ ## https://github.com/BoundaryML/baml/blob/canary/engine/language_client_ruby/x86-64_linux-setup.sh
5
+ ##
6
+
7
+ set -euxo pipefail
8
+
9
+ # from https://serverfault.com/questions/1161816/mirrorlist-centos-org-no-longer-resolve
10
+ sudo sed -i 's/mirror.centos.org/vault.centos.org/g' /etc/yum.repos.d/*.repo
11
+ sudo sed -i 's/^#.*baseurl=http/baseurl=http/g' /etc/yum.repos.d/*.repo
12
+ sudo sed -i 's/^mirrorlist=http/#mirrorlist=http/g' /etc/yum.repos.d/*.repo
13
+
14
+ ls /etc/yum.repos.d/
15
+
16
+ # We need this to build engine/, since it's needed for OpenSSL
17
+ sudo yum install -y perl-IPC-Cmd
@@ -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.1.2"
4
+ version = "3.2.2"
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 = "4.0.0" }
15
+ eppo_core = { version = "4.1.0", features = ["vendored"] }
16
16
  log = { version = "0.4.21", features = ["kv_serde"] }
17
- magnus = { version = "0.6.2" }
17
+ magnus = { version = "0.6.4" }
18
18
  serde = { version = "1.0.203", features = ["derive"] }
19
19
  serde_magnus = "0.8.1"
20
- rb-sys = "0.9"
20
+ rb-sys = "0.9.102"
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, SdkMetadata,
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
- Ok(Config { api_key, base_url })
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 sdk_metadata = SdkMetadata {
45
- name: "ruby",
46
- version: env!("CARGO_PKG_VERSION"),
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(Some(poller_thread)),
85
+ poller_thread: RefCell::new(poller_thread),
67
86
  }
68
87
  }
69
88
 
@@ -171,6 +190,17 @@ impl Client {
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
+ }
@@ -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
  }
@@ -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
@@ -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
@@ -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.1.2"
5
+ VERSION = "3.2.2"
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.1.2
4
+ version: 3.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eppo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-08 00:00:00.000000000 Z
11
+ date: 2024-10-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -27,10 +27,13 @@ files:
27
27
  - README.md
28
28
  - Rakefile
29
29
  - Steepfile
30
+ - build/x86-64_linux-setup.sh
30
31
  - ext/eppo_client/Cargo.toml
31
32
  - ext/eppo_client/build.rs
32
33
  - ext/eppo_client/extconf.rb
33
34
  - ext/eppo_client/src/client.rs
35
+ - ext/eppo_client/src/configuration.rs
36
+ - ext/eppo_client/src/gc_lock.rs
34
37
  - ext/eppo_client/src/lib.rs
35
38
  - lib/eppo_client.rb
36
39
  - lib/eppo_client/assignment_logger.rb