This provides SDK to interact with experimentation-platform
- Experimentation Client Integration
The rust client have a client factory that helps you work with multiple clients connected to different tenants
Create a client in the factory. You can chose to use the result to check for errors faced by the Client Factory while creating your client, it is not mandatory to consume the Ok
value.
pub async fn create_client(
tenant: String,
polling_interval: Duration,
hostname: String,
) -> Result<Arc<Client>, String>
Param | type | description | Example value |
---|---|---|---|
tenant |
String | specifies the tenants configs and contexts that will be loaded into the client at polling_interval from hostname |
mjos |
polling_interval |
Duration | specifies the time cac client waits before checking with the server for updates | Duration::from_secs(5) |
hostname |
String | The URL of the superposition server | https://superposition.example.com |
Get a client
pub async fn get_client(
tenant: String
) -> Result<Arc<Client>, String>
Param | type | description | Example value |
---|---|---|---|
tenant |
String | specifies the tenant used during create_client |
mjos |
Below is the rust implementation to instantiate Experimentation client .
use superpostion_client as sp;
let tenants: Vec<String> = ["dev", "test"];
//You can create a clientFactory
for tenant in tenants {
rt::spawn(
sp::CLIENT_FACTORY
.create_client(tenant.to_string(),
poll_frequency,//How frequently you want to update config in secs
hostname.to_string()// superposition hostname
)
.await
.expect(format!("{}: Failed to acquire experimentation_client", tenant).as_str())
.clone()
.run_polling_updates(),
);
};
//You can extract an individual tenant's client from clientFactory
let tenant = "dev".to_owned();
let sp_client = sp::CLIENT_FACTORY
.get_client(tenant.clone())
.await
.map_err(|e| {
log::error!("{}: {}", tenant, e);
ErrorType::IgnoreError(format!("{}: Failed to get experimentation_client", tenant))
})?;
the Experimentation client polls for updates from the superposition service and loads any changes done on the server. This means that experiments changed in superposition are reflected on the client in the duration of polling_interval
. run_polling_updates()
should be run in a separate thread, as it does not terminate.
pub async fn run_polling_updates()
When experiments are running, you can get different variants of the experiment based on the toss
value you provide. Superposition decides which bucket your request falls into based on this value, and returns an ID called the variantId
. You can then include this in your CAC client request.
The toss can be a random number between -1 to 100. You can log the variantId so that your metrics can help you decide on a variant
pub async fn get_applicable_variant(context: &Value, toss: i8) -> Vec<String>
Param | type | description | Example value |
---|---|---|---|
context |
Value | The context under which you want to resolve configs | {"os": "android", "merchant": "juspay"} |
toss |
i8 | an integer that assigns your request to a variant | 4 |
Rather than just getting the variant ID, you can get the whole experiment(s) that are satisfying your context - rather than just the final result.
pub async fn get_satisfied_experiments(context: &Value) -> Experiments
Param | type | description | Example value |
---|---|---|---|
context |
Value | The context under which you want to resolve configs | {"os": "android", "merchant": "juspay"} |
Get all running experiments, why would you want to do this? We don't know. But you can.
pub async fn get_running_experiments() -> Experiments
Create a client in the factory. You can chose to use the result to check for errors faced by the Client Factory while creating your client.
createExpClient:: Tenant -> Integer -> String -> IO (Either Error ())
Param | type | description | Example value |
---|---|---|---|
Tenant |
String | specifies the tenants configs and contexts that will be loaded into the client at polling_interval from hostname |
mjos |
Interval |
Integer | specifies the time cac client waits before checking with the server for updates | Duration::from_secs(5) |
Hostname |
String | The URL of the superposition server | https://superposition.example.com |
Get a client
getExpClient :: Tenant -> IO (Either Error (ForeignPtr ExpClient))
Param | type | description | Example value |
---|---|---|---|
tenant |
String | specifies the tenant used during create_client |
mjos |
the Experimentation client polls for updates from the superposition service and loads any changes done on the server. This means that experiments changed in superposition are reflected on the client in the duration of Interval
. expStartPolling
should be run in a separate thread, as it does not terminate.
expStartPolling :: Tenant -> IO ()
When experiments are running, you can get different variants of the experiment based on the toss
value you provide. Superposition decides which bucket your request falls into based on this value, and returns an ID called the variantId
. You can then include this in your CAC client request.
The toss can be a random number between -1 to 100. You can log the variantId so that your metrics can help you decide on a variant
getApplicableVariants :: ForeignPtr ExpClient -> String -> Integer -> IO (Either Error String)
Param | type | description | Example value |
---|---|---|---|
context |
String | The context under which you want to resolve configs | {"os": "android", "merchant": "juspay"} |
toss |
Integer | an integer that assigns your request to a variant | 4 |
Rather than just getting the variant ID, you can get the whole experiment(s) that are satisfying your context - rather than just the final result.
getSatisfiedExperiments :: ForeignPtr ExpClient -> String -> IO (Either Error Value)
Param | type | description | Example value |
---|---|---|---|
context |
Value | The context under which you want to resolve configs | {"os": "android", "merchant": "juspay"} |
Get all running experiments, why would you want to do this? We don't know. But you can.
getRunningExperiments :: ForeignPtr ExpClient -> IO (Either Error Value)
{-# LANGUAGE LambdaCase #-}
module Main (main) where
import Client (createExpClient, expStartPolling,
getApplicableVariants, getExpClient,
getRunningExperiments,
getSatisfiedExperiments)
import Control.Concurrent
import Prelude
main :: IO ()
main = do
createExpClient "dev" 10 "http://localhost:8080" >>= \case
Left err -> putStrLn err
Right _ -> pure ()
threadId <- forkIO (expStartPolling "dev")
print threadId
getExpClient "dev" >>= \case
Left err -> putStrLn err
Right client -> loop client
pure ()
where
loop client = do
runningExperiments <- getRunningExperiments client
satisfiedExperiments <- getSatisfiedExperiments client "{\"os\": \"android\", \"client\": \"1mg\"}"
variants <- getApplicableVariants client "{\"os\": \"android\", \"client\": \"1mg\"}" 9
print "Running experiments"
print runningExperiments
print "experiments that satisfy context"
print satisfiedExperiments
print "variant ID applied"
print variants
-- threadDelay 10000000
loop client