use futures::{future::BoxFuture, FutureExt};
use crate::{
bigtable,
builder::ClientBuilder,
emulator::{self, EmulatorData},
};
type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
pub struct EmulatorClient {
inner: crate::emulator::EmulatorClient,
instance: String,
}
const DATA: EmulatorData = EmulatorData {
gcloud_param: "bigtable",
kill_pattern: "bigtable",
availability_check: create_bigtable_client,
extra_args: Vec::new(),
};
const INSTANCE_ID: &str = "test-instance";
impl EmulatorClient {
pub async fn new() -> Result<Self, BoxError> {
Ok(EmulatorClient {
inner: emulator::EmulatorClient::new(DATA).await?,
instance: INSTANCE_ID.into(),
})
}
pub async fn with_project_and_instance(
project_name: impl Into<String>,
instance_name: impl Into<String>,
) -> Result<Self, BoxError> {
Ok(EmulatorClient {
inner: emulator::EmulatorClient::with_project(DATA, project_name).await?,
instance: instance_name.into(),
})
}
pub fn endpoint(&self) -> String {
self.inner.endpoint()
}
pub fn project(&self) -> &str {
self.inner.project()
}
pub fn instance(&self) -> &str {
&self.instance
}
pub fn builder(&self) -> &ClientBuilder {
self.inner.builder()
}
pub async fn create_table(
&self,
table_name: &str,
column_families: impl IntoIterator<Item = impl Into<String>>,
) -> Result<(), BoxError> {
let config = bigtable::admin::BigtableTableAdminConfig {
endpoint: self.endpoint(),
..bigtable::admin::BigtableTableAdminConfig::default()
};
let mut admin = self
.builder()
.build_bigtable_admin_client(config, &self.project(), &self.instance)
.await?;
let column_families = column_families
.into_iter()
.map(|name| (name.into(), bigtable::admin::Rule::MaxNumVersions(i32::MAX)));
admin.create_table(table_name, column_families).await?;
Ok(())
}
}
fn create_bigtable_client(port: &str) -> BoxFuture<Result<(), tonic::transport::Error>> {
async move {
bigtable::api::bigtable::v2::bigtable_client::BigtableClient::connect(format!(
"http://{}:{}",
crate::emulator::HOST,
port
))
.await?;
Ok(())
}
.boxed()
}