pub struct Cluster {
pub uuid: Uuid,
pub plugin_path: PathBuf,
pub data_dir: PathBuf,
pub timeout: Duration,
/* private fields */
}
Fields§
§uuid: Uuid
§plugin_path: PathBuf
§data_dir: PathBuf
§timeout: Duration
Implementations§
Source§impl Cluster
impl Cluster
pub fn new( plugin_path: PathBuf, topology: Topology, timeout: Duration, ) -> Result<Cluster, Error>
pub fn data_dir_path(&self) -> PathBuf
pub fn stop(&self) -> Result<(), Error>
Sourcepub fn apply_config<T>(&self, config: T) -> Result<(), Error>
pub fn apply_config<T>(&self, config: T) -> Result<(), Error>
Applies passed plugin config to the running cluster through the interface of command “pike config apply”.
§Arguments:
config
- mapping of plugin services to their values. This structure should be able to deserialize intoPluginConfigMap
.
§Returns
- On sucess, returns nothing.
- On failure, instance of
anyhow::Result
.
Note: your cluster logs may contain messages related to status of config applying. E.g., if some fields are erroneously serialized, Picodata plugin environment will throw a descriptive error during config validation saying what went wrong.
Thus, this routine will raise an error if something goes wrong, but details of an error rather be found in cluster logs.
§Examples:
§Plugin with single service called router
.
Assume plugin YAML configuration file has the following mapping:
router:
rpc_endpoint: "/hello"
max_rpc_message_size_bytes: 1024
max_rpc_message_queue_size: 2048
Our integration test will override all fields of service configuration
and apply new config through Cluster::apply_config
routine.
There’re several approaches of assembling PluginConfigMap
that is passed into the routine.
1. Using YAML formatted string.
Put desired config inside string and deserialize it using [serde_yaml::from_str
]. Then attach it to
a particular plugin service.
use rmpv::Value;
use std::collections::HashMap;
use serde_yaml::Value;
use picotest::*;
#[picotest]
fn test_apply_plugin_from_yaml_string() {
// 1. Assemble YAML string.
let plugin_config_yaml = r#"
router:
rpc_endpoint: "/test"
max_rpc_message_size_bytes: 128
max_rpc_message_queue_size: 32
"#;
let plugin_config: PluginConfigMap =
serde_yaml::from_str(plugin_config_yaml).unwrap();
// 2. Apply config to the running cluster instance.
cluster // implicitly created variable by picotest magic
.apply_config(plugin_config)
.expect("Failed to apply config");
// Callback Serivce::on_config_change should've been already
// called at this point.
}
**2. Using HashMap
.
Config can be assembled by means of std::collections::HashMap
and [serde_yaml::to_str
].
use rmpv::Value;
use std::collections::HashMap;
use serde_yaml::Value;
use picotest::*;
#[picotest]
fn test_apply_plugin_from_hashmap() {
// 1. Override properties of the "router" service.
let router_config = HashMap::from([
("rpc_endpoint".to_string(), Value::String("/test".into())),
("max_rpc_message_size_bytes".to_string(), Value::Number(128.into())),
("max_rpc_message_queue_size".to_string(), Value::Number(32.into())),
]);
// 2. "Attach" overridden properties to the service "router".
let plugin_config = HashMap::from([("router".into(), router_config)]);
// 3. Apply config to the running cluster instance.
cluster // implicitly created variable by picotest magic
.apply_config(plugin_config)
.expect("Failed to apply config");
// Callback Serivce::on_config_change should've been already
// called at this point.
}
§Plugin with single service called router
, which has nested properties for RPC machinery.
Nested sections in config mapping are handled similarly. We just need to wrap nested map value into [serde_yaml::Value
].
Assume plugin YAML configuration file has the following mapping:
router:
rpc:
endpoint: "/hello"
max_message_size_bytes: 1024
max_message_queue_size: 2048
Out integration test will look like:
use rmpv::Value;
use std::collections::HashMap;
use serde_yaml::Value;
use picotest::*;
#[picotest]
fn test_apply_plugin_nested_config() {
// Override properties of the RPC machinery.
let rpc_config = HashMap::from([
("endpoint".to_string(), Value::String("/test".into())),
("max_message_size_bytes".to_string(), Value::Number(128.into())),
("max_message_queue_size".to_string(), Value::Number(32.into())),
]);
let router_config = HashMap::from([("rpc".to_string(), serde_yaml::to_value(rpc_config).unwrap())]);
let plugin_config = HashMap::from([("router".to_string(), router_config)]);
cluster // implicitly created variable by picotest magic
.apply_config(plugin_config)
.expect("Failed to apply config");
}
pub fn run(self) -> Result<Cluster, Error>
pub fn recreate(self) -> Result<Cluster, Error>
Sourcepub fn run_query<T>(&self, query: T) -> Result<String, Error>
pub fn run_query<T>(&self, query: T) -> Result<String, Error>
Executes an SQL query through the picodata admin console.
§Workflow
- Establishes connection with the admin console (
await_picodata_admin
) - Writes the query to the process’s stdin
- Reads the result from stdout, skipping the first 2 lines (typically headers)
- Terminates the process after receiving the result
§Arguments
query
- SQL query as a byte slice or convertible type
§Return Value
Result<String, Error>
where:
Ok(String)
- query execution resultErr(Error)
- I/O or execution error
§Examples
use picotest::*;
#[picotest]
fn run_sql_query() {
let result = cluster.run_query("SELECT * FROM users").unwrap();
println!("{}", result);
}
Sourcepub fn run_lua<T>(&self, query: T) -> Result<String, Error>
pub fn run_lua<T>(&self, query: T) -> Result<String, Error>
Executes Lua script through picodata’s query mechanism.
Prepends \lua\n
to the query and passes it to run_query
.
§Arguments
query
- Lua code as a byte slice or convertible type
§Return Value
Result<String, Error>
where:
Ok(String)
- script execution resultErr(Error)
- execution error (inherited fromrun_query
)
§Examples
use picotest::*;
#[picotest]
fn test_run_lua_query() {
let res = cluster.instances()[1].run_lua("return 1 + 1")?;
assert!(res.contains("2"));
}
Sourcepub fn main(&self) -> &PicotestInstance
pub fn main(&self) -> &PicotestInstance
Method returns first running cluster instance
Sourcepub fn get_instances_by_tier(&self, tier_name: &str) -> Vec<&PicotestInstance>
pub fn get_instances_by_tier(&self, tier_name: &str) -> Vec<&PicotestInstance>
Method returns all instances, which belong to certain tier
Sourcepub fn instances(&self) -> &Vec<PicotestInstance>
pub fn instances(&self) -> &Vec<PicotestInstance>
Method returns all running instances of cluster
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Cluster
impl !RefUnwindSafe for Cluster
impl Send for Cluster
impl Sync for Cluster
impl Unpin for Cluster
impl !UnwindSafe for Cluster
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more