Skip to content

Commit

Permalink
Merge pull request #1840 from tursodatabase/opsqlite_offline
Browse files Browse the repository at this point in the history
Make it possible to use offline writes in C bindings
  • Loading branch information
haaawk authored Nov 25, 2024
2 parents a77f422 + 7e6d74f commit 3d52c07
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bindings/c/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tokio = { version = "1.29.1", features = [ "rt-multi-thread" ] }
hyper-rustls = { version = "0.25", features = ["webpki-roots"]}
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
http = "1.1.0"

[target.'cfg(not(any(target_os = "ios", target_os = "android")))'.dependencies]
libsql = { path = "../../libsql", features = ["encryption"] }
Expand Down
40 changes: 39 additions & 1 deletion bindings/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extern crate lazy_static;
mod types;

use crate::types::libsql_config;
use libsql::{errors, LoadExtensionGuard};
use libsql::{errors, Builder, LoadExtensionGuard};
use tokio::runtime::Runtime;
use types::{
blob, libsql_connection, libsql_connection_t, libsql_database, libsql_database_t, libsql_row,
Expand Down Expand Up @@ -152,6 +152,44 @@ pub unsafe extern "C" fn libsql_open_sync_with_config(
return 3;
}
};
let uri: http::Uri = match primary_url.try_into() {
Ok(uri) => uri,
Err(e) => {
set_err_msg(format!("Wrong primary URL: {e}"), out_err_msg);
return 100;
}
};
if let Some(query) = uri.query() {
if query.contains("offline") {
let mut builder = Builder::new_synced_database(
db_path,
primary_url.to_owned(),
auth_token.to_owned(),
);
if config.with_webpki != 0 {
let https = hyper_rustls::HttpsConnectorBuilder::new()
.with_webpki_roots()
.https_or_http()
.enable_http1()
.build();
builder = builder.connector(https);
}
match RT.block_on(builder.build()) {
Ok(db) => {
let db = Box::leak(Box::new(libsql_database { db }));
*out_db = libsql_database_t::from(db);
return 0;
}
Err(e) => {
set_err_msg(
format!("Error opening offline db path {db_path}, primary url {primary_url}: {e}"),
out_err_msg,
);
return 101;
}
}
}
}
let mut builder = libsql::Builder::new_remote_replica(
db_path,
primary_url.to_string(),
Expand Down
48 changes: 38 additions & 10 deletions libsql/src/database/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
cfg_core! {
use crate::EncryptionConfig;
}

use crate::{Database, Result};

use super::DbType;
Expand Down Expand Up @@ -99,6 +100,7 @@ impl Builder<()> {
connector: None,
version: None,
},
connector:None,
},
}
}
Expand Down Expand Up @@ -399,6 +401,7 @@ cfg_sync! {
path: std::path::PathBuf,
flags: crate::OpenFlags,
remote: Remote,
connector: Option<crate::util::ConnectorService>,
}

impl Builder<SyncedDatabase> {
Expand All @@ -408,6 +411,18 @@ cfg_sync! {
self
}

/// Provide a custom http connector that will be used to create http connections.
pub fn connector<C>(mut self, connector: C) -> Builder<SyncedDatabase>
where
C: tower::Service<http::Uri> + Send + Clone + Sync + 'static,
C::Response: crate::util::Socket,
C::Future: Send + 'static,
C::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
{
self.inner.connector = Some(wrap_connector(connector));
self
}

/// Build a connection to a local database that can be synced to remote server.
pub async fn build(self) -> Result<Database> {
let SyncedDatabase {
Expand All @@ -420,11 +435,16 @@ cfg_sync! {
connector: _,
version: _,
},
connector,
} = self.inner;

let path = path.to_str().ok_or(crate::Error::InvalidUTF8Path)?.to_owned();

let https = super::connector()?;
let https = if let Some(connector) = connector {
connector
} else {
wrap_connector(super::connector()?)
};
use tower::ServiceExt;

let svc = https
Expand Down Expand Up @@ -506,6 +526,22 @@ cfg_remote! {
}

cfg_replication_or_remote_or_sync! {
fn wrap_connector<C>(connector: C) -> crate::util::ConnectorService
where
C: tower::Service<http::Uri> + Send + Clone + Sync + 'static,
C::Response: crate::util::Socket,
C::Future: Send + 'static,
C::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
{
use tower::ServiceExt;

let svc = connector
.map_err(|e| e.into())
.map_response(|s| Box::new(s) as Box<dyn crate::util::Socket>);

crate::util::ConnectorService::new(svc)
}

impl Remote {
fn connector<C>(mut self, connector: C) -> Remote
where
Expand All @@ -514,15 +550,7 @@ cfg_replication_or_remote_or_sync! {
C::Future: Send + 'static,
C::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
{
use tower::ServiceExt;

let svc = connector
.map_err(|e| e.into())
.map_response(|s| Box::new(s) as Box<dyn crate::util::Socket>);

let svc = crate::util::ConnectorService::new(svc);

self.connector = Some(svc);
self.connector = Some(wrap_connector(connector));
self
}

Expand Down

0 comments on commit 3d52c07

Please sign in to comment.