postgres.rs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. use std::sync::Arc;
  2. use cdk_postgres::PgConnectionPool;
  3. use crate::{
  4. CurrencyUnit, FfiError, FfiWalletSQLDatabase, Id, KeySet, KeySetInfo, Keys, MeltQuote,
  5. MintInfo, MintQuote, MintUrl, ProofInfo, ProofState, PublicKey, SpendingConditions,
  6. Transaction, TransactionDirection, TransactionId, WalletDatabase,
  7. };
  8. #[derive(uniffi::Object)]
  9. pub struct WalletPostgresDatabase {
  10. inner: Arc<FfiWalletSQLDatabase<PgConnectionPool>>,
  11. }
  12. // Keep a long-lived Tokio runtime for Postgres-created resources so that
  13. // background tasks (e.g., tokio-postgres connection drivers spawned during
  14. // construction) are not tied to a short-lived, ad-hoc runtime.
  15. #[cfg(feature = "postgres")]
  16. static PG_RUNTIME: once_cell::sync::OnceCell<tokio::runtime::Runtime> =
  17. once_cell::sync::OnceCell::new();
  18. #[cfg(feature = "postgres")]
  19. fn pg_runtime() -> &'static tokio::runtime::Runtime {
  20. PG_RUNTIME.get_or_init(|| {
  21. tokio::runtime::Builder::new_multi_thread()
  22. .enable_all()
  23. .thread_name("cdk-ffi-pg")
  24. .build()
  25. .expect("failed to build pg runtime")
  26. })
  27. }
  28. #[uniffi::export]
  29. impl WalletPostgresDatabase {
  30. /// Create a new Postgres-backed wallet database
  31. /// Requires cdk-ffi to be built with feature "postgres".
  32. /// Example URL:
  33. /// "host=localhost user=test password=test dbname=testdb port=5433 schema=wallet sslmode=prefer"
  34. #[cfg(feature = "postgres")]
  35. #[uniffi::constructor]
  36. pub fn new(url: String) -> Result<Arc<Self>, FfiError> {
  37. let inner = match tokio::runtime::Handle::try_current() {
  38. Ok(handle) => tokio::task::block_in_place(|| {
  39. handle.block_on(
  40. async move { cdk_postgres::new_wallet_pg_database(url.as_str()).await },
  41. )
  42. }),
  43. // Important: use a process-long runtime so background connection tasks stay alive.
  44. Err(_) => pg_runtime()
  45. .block_on(async move { cdk_postgres::new_wallet_pg_database(url.as_str()).await }),
  46. }
  47. .map_err(|e| FfiError::Database { msg: e.to_string() })?;
  48. Ok(Arc::new(WalletPostgresDatabase {
  49. inner: FfiWalletSQLDatabase::new(inner),
  50. }))
  51. }
  52. }
  53. // Use macro to implement WalletDatabase trait - delegates all methods to inner
  54. crate::impl_ffi_wallet_database!(WalletPostgresDatabase);