database.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. use async_trait::async_trait;
  2. use hbb_common::{log, ResultType};
  3. use sqlx::{
  4. sqlite::SqliteConnectOptions, ConnectOptions, Connection, Error as SqlxError, SqliteConnection,
  5. };
  6. use std::{ops::DerefMut, str::FromStr};
  7. //use sqlx::postgres::PgPoolOptions;
  8. //use sqlx::mysql::MySqlPoolOptions;
  9. type Pool = deadpool::managed::Pool<DbPool>;
  10. pub struct DbPool {
  11. url: String,
  12. }
  13. #[async_trait]
  14. impl deadpool::managed::Manager for DbPool {
  15. type Type = SqliteConnection;
  16. type Error = SqlxError;
  17. async fn create(&self) -> Result<SqliteConnection, SqlxError> {
  18. let mut opt = SqliteConnectOptions::from_str(&self.url).unwrap();
  19. opt.log_statements(log::LevelFilter::Debug);
  20. SqliteConnection::connect_with(&opt).await
  21. }
  22. async fn recycle(
  23. &self,
  24. obj: &mut SqliteConnection,
  25. ) -> deadpool::managed::RecycleResult<SqlxError> {
  26. Ok(obj.ping().await?)
  27. }
  28. }
  29. #[derive(Clone)]
  30. pub struct Database {
  31. pool: Pool,
  32. }
  33. #[derive(Default)]
  34. pub struct Peer {
  35. pub guid: Vec<u8>,
  36. pub id: String,
  37. pub uuid: Vec<u8>,
  38. pub pk: Vec<u8>,
  39. pub user: Option<Vec<u8>>,
  40. pub info: String,
  41. pub status: Option<i64>,
  42. }
  43. impl Database {
  44. pub async fn new(url: &str) -> ResultType<Database> {
  45. if !std::path::Path::new(url).exists() {
  46. std::fs::File::create(url).ok();
  47. }
  48. let n: usize = std::env::var("MAX_DATABASE_CONNECTIONS")
  49. .unwrap_or_else(|_| "1".to_owned())
  50. .parse()
  51. .unwrap_or(1);
  52. log::debug!("MAX_DATABASE_CONNECTIONS={}", n);
  53. let pool = Pool::new(
  54. DbPool {
  55. url: url.to_owned(),
  56. },
  57. n,
  58. );
  59. let _ = pool.get().await?; // test
  60. let db = Database { pool };
  61. db.create_tables().await?;
  62. Ok(db)
  63. }
  64. async fn create_tables(&self) -> ResultType<()> {
  65. sqlx::query!(
  66. "
  67. create table if not exists peer (
  68. guid blob primary key not null,
  69. id varchar(100) not null,
  70. uuid blob not null,
  71. pk blob not null,
  72. created_at datetime not null default(current_timestamp),
  73. user blob,
  74. status tinyint,
  75. note varchar(300),
  76. info text not null
  77. ) without rowid;
  78. create unique index if not exists index_peer_id on peer (id);
  79. create index if not exists index_peer_user on peer (user);
  80. create index if not exists index_peer_created_at on peer (created_at);
  81. create index if not exists index_peer_status on peer (status);
  82. "
  83. )
  84. .execute(self.pool.get().await?.deref_mut())
  85. .await?;
  86. Ok(())
  87. }
  88. pub async fn get_peer(&self, id: &str) -> ResultType<Option<Peer>> {
  89. Ok(sqlx::query_as!(
  90. Peer,
  91. "select guid, id, uuid, pk, user, status, info from peer where id = ?",
  92. id
  93. )
  94. .fetch_optional(self.pool.get().await?.deref_mut())
  95. .await?)
  96. }
  97. pub async fn insert_peer(
  98. &self,
  99. id: &str,
  100. uuid: &[u8],
  101. pk: &[u8],
  102. info: &str,
  103. ) -> ResultType<Vec<u8>> {
  104. let guid = uuid::Uuid::new_v4().as_bytes().to_vec();
  105. sqlx::query!(
  106. "insert into peer(guid, id, uuid, pk, info) values(?, ?, ?, ?, ?)",
  107. guid,
  108. id,
  109. uuid,
  110. pk,
  111. info
  112. )
  113. .execute(self.pool.get().await?.deref_mut())
  114. .await?;
  115. Ok(guid)
  116. }
  117. pub async fn update_pk(
  118. &self,
  119. guid: &Vec<u8>,
  120. id: &str,
  121. pk: &[u8],
  122. info: &str,
  123. ) -> ResultType<()> {
  124. sqlx::query!(
  125. "update peer set id=?, pk=?, info=? where guid=?",
  126. id,
  127. pk,
  128. info,
  129. guid
  130. )
  131. .execute(self.pool.get().await?.deref_mut())
  132. .await?;
  133. Ok(())
  134. }
  135. }
  136. #[cfg(test)]
  137. mod tests {
  138. use hbb_common::tokio;
  139. #[test]
  140. fn test_insert() {
  141. insert();
  142. }
  143. #[tokio::main(flavor = "multi_thread")]
  144. async fn insert() {
  145. let db = super::Database::new("test.sqlite3").await.unwrap();
  146. let mut jobs = vec![];
  147. for i in 0..10000 {
  148. let cloned = db.clone();
  149. let id = i.to_string();
  150. let a = tokio::spawn(async move {
  151. let empty_vec = Vec::new();
  152. cloned
  153. .insert_peer(&id, &empty_vec, &empty_vec, "")
  154. .await
  155. .unwrap();
  156. });
  157. jobs.push(a);
  158. }
  159. for i in 0..10000 {
  160. let cloned = db.clone();
  161. let id = i.to_string();
  162. let a = tokio::spawn(async move {
  163. cloned.get_peer(&id).await.unwrap();
  164. });
  165. jobs.push(a);
  166. }
  167. hbb_common::futures::future::join_all(jobs).await;
  168. }
  169. }