Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ pub use self::foundationdb::Foundationdb;
mod postgresql;
#[cfg(feature = "services-postgresql")]
pub use self::postgresql::Postgresql;
#[cfg(feature = "services-postgresql")]
pub use self::postgresql::PostgresqlConfig;

#[cfg(feature = "services-atomicserver")]
mod atomicserver;
Expand Down
85 changes: 57 additions & 28 deletions core/src/services/postgresql/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,64 @@ use std::sync::Arc;
use async_trait::async_trait;
use bb8::Pool;
use bb8_postgres::PostgresConnectionManager;
use serde::Deserialize;
use tokio::sync::OnceCell;
use tokio_postgres::Config;

use crate::raw::adapters::kv;
use crate::raw::*;
use crate::*;

/// [Postgresql](https://www.postgresql.org/) services support.
#[doc = include_str!("docs.md")]
#[derive(Default)]
pub struct PostgresqlBuilder {
/// Config for PostGresQL services support.
#[derive(Default, Deserialize)]
#[serde(default)]
#[non_exhaustive]
pub struct PostgresqlConfig {
/// root of this backend.
///
/// All operations will happen under this root.
///
/// default to `/` if not set.
pub root: Option<String>,
/// the connection string of postgres server
connection_string: Option<String>,

/// the table of postgresql
table: Option<String>,
/// the key field of postgresql
key_field: Option<String>,
/// the value field of postgresql
value_field: Option<String>,
root: Option<String>,
}

impl Debug for PostgresqlConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut d = f.debug_struct("PostgresqlConfig");

if self.connection_string.is_some() {
d.field("connection_string", &"<redacted>");
}

d.field("root", &self.root)
.field("table", &self.table)
.field("key_field", &self.key_field)
.field("value_field", &self.value_field)
.finish()
}
}

/// [Postgresql](https://www.postgresql.org/) services support.
#[doc = include_str!("docs.md")]
#[derive(Default)]
pub struct PostgresqlBuilder {
config: PostgresqlConfig,
}

impl Debug for PostgresqlBuilder {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Builder");
ds.field("table", &self.table);
ds.finish()
let mut d = f.debug_struct("PostgresqlBuilder");

d.field("config", &self.config);
d.finish()
}
}

Expand Down Expand Up @@ -84,7 +118,7 @@ impl PostgresqlBuilder {
/// For more information, please visit <https://docs.rs/postgres/latest/postgres/config/struct.Config.html>
pub fn connection_string(&mut self, v: &str) -> &mut Self {
if !v.is_empty() {
self.connection_string = Some(v.to_string());
self.config.connection_string = Some(v.to_string());
}
self
}
Expand All @@ -94,15 +128,15 @@ impl PostgresqlBuilder {
/// default: "/"
pub fn root(&mut self, root: &str) -> &mut Self {
if !root.is_empty() {
self.root = Some(root.to_owned());
self.config.root = Some(root.to_owned());
}
self
}

/// Set the table name of the postgresql service to read/write.
pub fn table(&mut self, table: &str) -> &mut Self {
if !table.is_empty() {
self.table = Some(table.to_string());
self.config.table = Some(table.to_string());
}
self
}
Expand All @@ -112,7 +146,7 @@ impl PostgresqlBuilder {
/// Default to `key` if not specified.
pub fn key_field(&mut self, key_field: &str) -> &mut Self {
if !key_field.is_empty() {
self.key_field = Some(key_field.to_string());
self.config.key_field = Some(key_field.to_string());
}
self
}
Expand All @@ -122,7 +156,7 @@ impl PostgresqlBuilder {
/// Default to `value` if not specified.
pub fn value_field(&mut self, value_field: &str) -> &mut Self {
if !value_field.is_empty() {
self.value_field = Some(value_field.to_string());
self.config.value_field = Some(value_field.to_string());
}
self
}
Expand All @@ -133,20 +167,14 @@ impl Builder for PostgresqlBuilder {
type Accessor = PostgresqlBackend;

fn from_map(map: HashMap<String, String>) -> Self {
let mut builder = PostgresqlBuilder::default();

map.get("connection_string")
.map(|v| builder.connection_string(v));
map.get("table").map(|v| builder.table(v));
map.get("key_field").map(|v| builder.key_field(v));
map.get("value_field").map(|v| builder.value_field(v));
map.get("root").map(|v| builder.root(v));
let config = PostgresqlConfig::deserialize(ConfigDeserializer::new(map))
.expect("config deserialize must succeed");

builder
PostgresqlBuilder { config }
}

fn build(&mut self) -> Result<Self::Accessor> {
let conn = match self.connection_string.clone() {
let conn = match self.config.connection_string.clone() {
Some(v) => v,
None => {
return Err(
Expand All @@ -162,23 +190,24 @@ impl Builder for PostgresqlBuilder {
.set_source(err)
})?;

let table = match self.table.clone() {
let table = match self.config.table.clone() {
Some(v) => v,
None => {
return Err(Error::new(ErrorKind::ConfigInvalid, "table is empty")
.with_context("service", Scheme::Postgresql))
}
};
let key_field = match self.key_field.clone() {
let key_field = match self.config.key_field.clone() {
Some(v) => v,
None => "key".to_string(),
};
let value_field = match self.value_field.clone() {
let value_field = match self.config.value_field.clone() {
Some(v) => v,
None => "value".to_string(),
};
let root = normalize_root(
self.root
self.config
.root
.clone()
.unwrap_or_else(|| "/".to_string())
.as_str(),
Expand Down
1 change: 1 addition & 0 deletions core/src/services/postgresql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@

mod backend;
pub use backend::PostgresqlBuilder as Postgresql;
pub use backend::PostgresqlConfig;
Comment thread
sd44 marked this conversation as resolved.