mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 10:29:35 +03:00
Reorganize source files of collab::db
* Move all sea_orm tables into a 'tables' module * Move TestDb into its own file * Move id types into their own module
This commit is contained in:
parent
e48bb1853c
commit
e964137d79
@ -1,56 +1,47 @@
|
||||
mod access_token;
|
||||
mod channel;
|
||||
mod channel_member;
|
||||
mod channel_path;
|
||||
mod contact;
|
||||
mod follower;
|
||||
mod language_server;
|
||||
mod project;
|
||||
mod project_collaborator;
|
||||
mod room;
|
||||
mod room_participant;
|
||||
mod server;
|
||||
mod signup;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod user;
|
||||
mod worktree;
|
||||
mod worktree_diagnostic_summary;
|
||||
mod worktree_entry;
|
||||
mod worktree_repository;
|
||||
mod worktree_repository_statuses;
|
||||
mod worktree_settings_file;
|
||||
mod db_tests;
|
||||
mod ids;
|
||||
mod tables;
|
||||
#[cfg(test)]
|
||||
pub mod test_db;
|
||||
|
||||
use crate::executor::Executor;
|
||||
use crate::{Error, Result};
|
||||
use anyhow::anyhow;
|
||||
use collections::{BTreeMap, HashMap, HashSet};
|
||||
pub use contact::Contact;
|
||||
use dashmap::DashMap;
|
||||
use futures::StreamExt;
|
||||
use hyper::StatusCode;
|
||||
use rand::prelude::StdRng;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rpc::{proto, ConnectionId};
|
||||
use sea_orm::Condition;
|
||||
pub use sea_orm::ConnectOptions;
|
||||
use sea_orm::{
|
||||
entity::prelude::*, ActiveValue, ConnectionTrait, DatabaseConnection, DatabaseTransaction,
|
||||
DbErr, FromQueryResult, IntoActiveModel, IsolationLevel, JoinType, QueryOrder, QuerySelect,
|
||||
Statement, TransactionTrait,
|
||||
entity::prelude::*, ActiveValue, Condition, ConnectionTrait, DatabaseConnection,
|
||||
DatabaseTransaction, DbErr, FromQueryResult, IntoActiveModel, IsolationLevel, JoinType,
|
||||
QueryOrder, QuerySelect, Statement, TransactionTrait,
|
||||
};
|
||||
use sea_query::{Alias, Expr, OnConflict, Query};
|
||||
use serde::{Deserialize, Serialize};
|
||||
pub use signup::{Invite, NewSignup, WaitlistSummary};
|
||||
use sqlx::migrate::{Migrate, Migration, MigrationSource};
|
||||
use sqlx::Connection;
|
||||
use std::fmt::Write as _;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use std::{future::Future, marker::PhantomData, rc::Rc, sync::Arc};
|
||||
use sqlx::{
|
||||
migrate::{Migrate, Migration, MigrationSource},
|
||||
Connection,
|
||||
};
|
||||
use std::{
|
||||
fmt::Write as _,
|
||||
future::Future,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
path::Path,
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use tables::*;
|
||||
use tokio::sync::{Mutex, OwnedMutexGuard};
|
||||
pub use user::Model as User;
|
||||
|
||||
pub use ids::*;
|
||||
pub use sea_orm::ConnectOptions;
|
||||
pub use tables::user::Model as User;
|
||||
|
||||
pub struct Database {
|
||||
options: ConnectOptions,
|
||||
@ -4083,6 +4074,60 @@ impl<T> RoomGuard<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Contact {
|
||||
Accepted {
|
||||
user_id: UserId,
|
||||
should_notify: bool,
|
||||
busy: bool,
|
||||
},
|
||||
Outgoing {
|
||||
user_id: UserId,
|
||||
},
|
||||
Incoming {
|
||||
user_id: UserId,
|
||||
should_notify: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Contact {
|
||||
pub fn user_id(&self) -> UserId {
|
||||
match self {
|
||||
Contact::Accepted { user_id, .. } => *user_id,
|
||||
Contact::Outgoing { user_id } => *user_id,
|
||||
Contact::Incoming { user_id, .. } => *user_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Invite {
|
||||
pub email_address: String,
|
||||
pub email_confirmation_code: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct NewSignup {
|
||||
pub email_address: String,
|
||||
pub platform_mac: bool,
|
||||
pub platform_windows: bool,
|
||||
pub platform_linux: bool,
|
||||
pub editor_features: Vec<String>,
|
||||
pub programming_languages: Vec<String>,
|
||||
pub device_id: Option<String>,
|
||||
pub added_to_mailing_list: bool,
|
||||
pub created_at: Option<DateTime>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, FromQueryResult)]
|
||||
pub struct WaitlistSummary {
|
||||
pub count: i64,
|
||||
pub linux_count: i64,
|
||||
pub mac_count: i64,
|
||||
pub windows_count: i64,
|
||||
pub unknown_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct NewUserParams {
|
||||
pub github_login: String,
|
||||
@ -4120,139 +4165,6 @@ fn random_email_confirmation_code() -> String {
|
||||
nanoid::nanoid!(64)
|
||||
}
|
||||
|
||||
macro_rules! id_type {
|
||||
($name:ident) => {
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct $name(pub i32);
|
||||
|
||||
impl $name {
|
||||
#[allow(unused)]
|
||||
pub const MAX: Self = Self(i32::MAX);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn from_proto(value: u64) -> Self {
|
||||
Self(value as i32)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn to_proto(self) -> u64 {
|
||||
self.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for sea_query::Value {
|
||||
fn from(value: $name) -> Self {
|
||||
sea_query::Value::Int(Some(value.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_orm::TryGetable for $name {
|
||||
fn try_get(
|
||||
res: &sea_orm::QueryResult,
|
||||
pre: &str,
|
||||
col: &str,
|
||||
) -> Result<Self, sea_orm::TryGetError> {
|
||||
Ok(Self(i32::try_get(res, pre, col)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::ValueType for $name {
|
||||
fn try_from(v: Value) -> Result<Self, sea_query::ValueTypeErr> {
|
||||
match v {
|
||||
Value::TinyInt(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::SmallInt(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::Int(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::BigInt(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::TinyUnsigned(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::SmallUnsigned(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::Unsigned(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
Value::BigUnsigned(Some(int)) => {
|
||||
Ok(Self(int.try_into().map_err(|_| sea_query::ValueTypeErr)?))
|
||||
}
|
||||
_ => Err(sea_query::ValueTypeErr),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_name() -> String {
|
||||
stringify!($name).into()
|
||||
}
|
||||
|
||||
fn array_type() -> sea_query::ArrayType {
|
||||
sea_query::ArrayType::Int
|
||||
}
|
||||
|
||||
fn column_type() -> sea_query::ColumnType {
|
||||
sea_query::ColumnType::Integer(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_orm::TryFromU64 for $name {
|
||||
fn try_from_u64(n: u64) -> Result<Self, DbErr> {
|
||||
Ok(Self(n.try_into().map_err(|_| {
|
||||
DbErr::ConvertFromU64(concat!(
|
||||
"error converting ",
|
||||
stringify!($name),
|
||||
" to u64"
|
||||
))
|
||||
})?))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::Nullable for $name {
|
||||
fn null() -> Value {
|
||||
Value::Int(None)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
id_type!(AccessTokenId);
|
||||
id_type!(ChannelId);
|
||||
id_type!(ChannelMemberId);
|
||||
id_type!(ContactId);
|
||||
id_type!(FollowerId);
|
||||
id_type!(RoomId);
|
||||
id_type!(RoomParticipantId);
|
||||
id_type!(ProjectId);
|
||||
id_type!(ProjectCollaboratorId);
|
||||
id_type!(ReplicaId);
|
||||
id_type!(ServerId);
|
||||
id_type!(SignupId);
|
||||
id_type!(UserId);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct JoinRoom {
|
||||
pub room: proto::Room,
|
||||
@ -4370,130 +4282,3 @@ pub struct WorktreeSettingsFile {
|
||||
enum QueryUserIds {
|
||||
UserId,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub use test::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use gpui::executor::Background;
|
||||
use parking_lot::Mutex;
|
||||
use sea_orm::ConnectionTrait;
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct TestDb {
|
||||
pub db: Option<Arc<Database>>,
|
||||
pub connection: Option<sqlx::AnyConnection>,
|
||||
}
|
||||
|
||||
impl TestDb {
|
||||
pub fn sqlite(background: Arc<Background>) -> Self {
|
||||
let url = format!("sqlite::memory:");
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut db = runtime.block_on(async {
|
||||
let mut options = ConnectOptions::new(url);
|
||||
options.max_connections(5);
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let sql = include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/migrations.sqlite/20221109000000_test_schema.sql"
|
||||
));
|
||||
db.pool
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
db.pool.get_database_backend(),
|
||||
sql.into(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
db.runtime = Some(runtime);
|
||||
|
||||
Self {
|
||||
db: Some(Arc::new(db)),
|
||||
connection: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn postgres(background: Arc<Background>) -> Self {
|
||||
static LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
let _guard = LOCK.lock();
|
||||
let mut rng = StdRng::from_entropy();
|
||||
let url = format!(
|
||||
"postgres://postgres@localhost/zed-test-{}",
|
||||
rng.gen::<u128>()
|
||||
);
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut db = runtime.block_on(async {
|
||||
sqlx::Postgres::create_database(&url)
|
||||
.await
|
||||
.expect("failed to create test db");
|
||||
let mut options = ConnectOptions::new(url);
|
||||
options
|
||||
.max_connections(5)
|
||||
.idle_timeout(Duration::from_secs(0));
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let migrations_path = concat!(env!("CARGO_MANIFEST_DIR"), "/migrations");
|
||||
db.migrate(Path::new(migrations_path), false).await.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
db.runtime = Some(runtime);
|
||||
|
||||
Self {
|
||||
db: Some(Arc::new(db)),
|
||||
connection: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn db(&self) -> &Arc<Database> {
|
||||
self.db.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestDb {
|
||||
fn drop(&mut self) {
|
||||
let db = self.db.take().unwrap();
|
||||
if let sea_orm::DatabaseBackend::Postgres = db.pool.get_database_backend() {
|
||||
db.runtime.as_ref().unwrap().block_on(async {
|
||||
use util::ResultExt;
|
||||
let query = "
|
||||
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
||||
FROM pg_stat_activity
|
||||
WHERE
|
||||
pg_stat_activity.datname = current_database() AND
|
||||
pid <> pg_backend_pid();
|
||||
";
|
||||
db.pool
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
db.pool.get_database_backend(),
|
||||
query.into(),
|
||||
))
|
||||
.await
|
||||
.log_err();
|
||||
sqlx::Postgres::drop_database(db.options.get_url())
|
||||
.await
|
||||
.log_err();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use super::*;
|
||||
use gpui::executor::{Background, Deterministic};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(test)]
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
use std::sync::Arc;
|
||||
use test_db::TestDb;
|
||||
|
||||
macro_rules! test_both_dbs {
|
||||
($postgres_test_name:ident, $sqlite_test_name:ident, $db:ident, $body:block) => {
|
125
crates/collab/src/db/ids.rs
Normal file
125
crates/collab/src/db/ids.rs
Normal file
@ -0,0 +1,125 @@
|
||||
use crate::Result;
|
||||
use sea_orm::DbErr;
|
||||
use sea_query::{Value, ValueTypeErr};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
macro_rules! id_type {
|
||||
($name:ident) => {
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Default,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct $name(pub i32);
|
||||
|
||||
impl $name {
|
||||
#[allow(unused)]
|
||||
pub const MAX: Self = Self(i32::MAX);
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn from_proto(value: u64) -> Self {
|
||||
Self(value as i32)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn to_proto(self) -> u64 {
|
||||
self.0 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$name> for sea_query::Value {
|
||||
fn from(value: $name) -> Self {
|
||||
sea_query::Value::Int(Some(value.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_orm::TryGetable for $name {
|
||||
fn try_get(
|
||||
res: &sea_orm::QueryResult,
|
||||
pre: &str,
|
||||
col: &str,
|
||||
) -> Result<Self, sea_orm::TryGetError> {
|
||||
Ok(Self(i32::try_get(res, pre, col)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::ValueType for $name {
|
||||
fn try_from(v: Value) -> Result<Self, sea_query::ValueTypeErr> {
|
||||
Ok(Self(value_to_integer(v)?))
|
||||
}
|
||||
|
||||
fn type_name() -> String {
|
||||
stringify!($name).into()
|
||||
}
|
||||
|
||||
fn array_type() -> sea_query::ArrayType {
|
||||
sea_query::ArrayType::Int
|
||||
}
|
||||
|
||||
fn column_type() -> sea_query::ColumnType {
|
||||
sea_query::ColumnType::Integer(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_orm::TryFromU64 for $name {
|
||||
fn try_from_u64(n: u64) -> Result<Self, DbErr> {
|
||||
Ok(Self(n.try_into().map_err(|_| {
|
||||
DbErr::ConvertFromU64(concat!(
|
||||
"error converting ",
|
||||
stringify!($name),
|
||||
" to u64"
|
||||
))
|
||||
})?))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::Nullable for $name {
|
||||
fn null() -> Value {
|
||||
Value::Int(None)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn value_to_integer(v: Value) -> Result<i32, ValueTypeErr> {
|
||||
match v {
|
||||
Value::TinyInt(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::SmallInt(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::Int(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::BigInt(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::TinyUnsigned(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::SmallUnsigned(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::Unsigned(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
Value::BigUnsigned(Some(int)) => int.try_into().map_err(|_| ValueTypeErr),
|
||||
_ => Err(ValueTypeErr),
|
||||
}
|
||||
}
|
||||
|
||||
id_type!(AccessTokenId);
|
||||
id_type!(ChannelId);
|
||||
id_type!(ChannelMemberId);
|
||||
id_type!(ContactId);
|
||||
id_type!(FollowerId);
|
||||
id_type!(RoomId);
|
||||
id_type!(RoomParticipantId);
|
||||
id_type!(ProjectId);
|
||||
id_type!(ProjectCollaboratorId);
|
||||
id_type!(ReplicaId);
|
||||
id_type!(ServerId);
|
||||
id_type!(SignupId);
|
||||
id_type!(UserId);
|
@ -1,57 +0,0 @@
|
||||
use super::{SignupId, UserId};
|
||||
use sea_orm::{entity::prelude::*, FromQueryResult};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "signups")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: SignupId,
|
||||
pub email_address: String,
|
||||
pub email_confirmation_code: String,
|
||||
pub email_confirmation_sent: bool,
|
||||
pub created_at: DateTime,
|
||||
pub device_id: Option<String>,
|
||||
pub user_id: Option<UserId>,
|
||||
pub inviting_user_id: Option<UserId>,
|
||||
pub platform_mac: bool,
|
||||
pub platform_linux: bool,
|
||||
pub platform_windows: bool,
|
||||
pub platform_unknown: bool,
|
||||
pub editor_features: Option<Vec<String>>,
|
||||
pub programming_languages: Option<Vec<String>>,
|
||||
pub added_to_mailing_list: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromQueryResult, Serialize, Deserialize)]
|
||||
pub struct Invite {
|
||||
pub email_address: String,
|
||||
pub email_confirmation_code: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct NewSignup {
|
||||
pub email_address: String,
|
||||
pub platform_mac: bool,
|
||||
pub platform_windows: bool,
|
||||
pub platform_linux: bool,
|
||||
pub editor_features: Vec<String>,
|
||||
pub programming_languages: Vec<String>,
|
||||
pub device_id: Option<String>,
|
||||
pub added_to_mailing_list: bool,
|
||||
pub created_at: Option<DateTime>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, FromQueryResult)]
|
||||
pub struct WaitlistSummary {
|
||||
pub count: i64,
|
||||
pub linux_count: i64,
|
||||
pub mac_count: i64,
|
||||
pub windows_count: i64,
|
||||
pub unknown_count: i64,
|
||||
}
|
20
crates/collab/src/db/tables.rs
Normal file
20
crates/collab/src/db/tables.rs
Normal file
@ -0,0 +1,20 @@
|
||||
pub mod access_token;
|
||||
pub mod channel;
|
||||
pub mod channel_member;
|
||||
pub mod channel_path;
|
||||
pub mod contact;
|
||||
pub mod follower;
|
||||
pub mod language_server;
|
||||
pub mod project;
|
||||
pub mod project_collaborator;
|
||||
pub mod room;
|
||||
pub mod room_participant;
|
||||
pub mod server;
|
||||
pub mod signup;
|
||||
pub mod user;
|
||||
pub mod worktree;
|
||||
pub mod worktree_diagnostic_summary;
|
||||
pub mod worktree_entry;
|
||||
pub mod worktree_repository;
|
||||
pub mod worktree_repository_statuses;
|
||||
pub mod worktree_settings_file;
|
@ -1,4 +1,4 @@
|
||||
use super::{AccessTokenId, UserId};
|
||||
use crate::db::{AccessTokenId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ChannelId;
|
||||
use crate::db::ChannelId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
||||
@ -30,9 +30,3 @@ impl Related<super::room::Entity> for Entity {
|
||||
Relation::Room.def()
|
||||
}
|
||||
}
|
||||
|
||||
// impl Related<super::follower::Entity> for Entity {
|
||||
// fn to() -> RelationDef {
|
||||
// Relation::Follower.def()
|
||||
// }
|
||||
// }
|
@ -1,6 +1,4 @@
|
||||
use crate::db::channel_member;
|
||||
|
||||
use super::{ChannelId, ChannelMemberId, UserId};
|
||||
use crate::db::{channel_member, ChannelId, ChannelMemberId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ChannelId;
|
||||
use crate::db::ChannelId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::{ContactId, UserId};
|
||||
use crate::db::{ContactId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
||||
@ -30,29 +30,3 @@ pub enum Relation {
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Contact {
|
||||
Accepted {
|
||||
user_id: UserId,
|
||||
should_notify: bool,
|
||||
busy: bool,
|
||||
},
|
||||
Outgoing {
|
||||
user_id: UserId,
|
||||
},
|
||||
Incoming {
|
||||
user_id: UserId,
|
||||
should_notify: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Contact {
|
||||
pub fn user_id(&self) -> UserId {
|
||||
match self {
|
||||
Contact::Accepted { user_id, .. } => *user_id,
|
||||
Contact::Outgoing { user_id } => *user_id,
|
||||
Contact::Incoming { user_id, .. } => *user_id,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
use super::{FollowerId, ProjectId, RoomId, ServerId};
|
||||
use crate::db::{FollowerId, ProjectId, RoomId, ServerId};
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel, Serialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "followers")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::{ProjectId, Result, RoomId, ServerId, UserId};
|
||||
use crate::db::{ProjectId, Result, RoomId, ServerId, UserId};
|
||||
use anyhow::anyhow;
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
@ -1,4 +1,4 @@
|
||||
use super::{ProjectCollaboratorId, ProjectId, ReplicaId, ServerId, UserId};
|
||||
use crate::db::{ProjectCollaboratorId, ProjectId, ReplicaId, ServerId, UserId};
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{ChannelId, RoomId};
|
||||
use crate::db::{ChannelId, RoomId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Default, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::{ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
|
||||
use crate::db::{ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ServerId;
|
||||
use crate::db::ServerId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
28
crates/collab/src/db/tables/signup.rs
Normal file
28
crates/collab/src/db/tables/signup.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::db::{SignupId, UserId};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "signups")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: SignupId,
|
||||
pub email_address: String,
|
||||
pub email_confirmation_code: String,
|
||||
pub email_confirmation_sent: bool,
|
||||
pub created_at: DateTime,
|
||||
pub device_id: Option<String>,
|
||||
pub user_id: Option<UserId>,
|
||||
pub inviting_user_id: Option<UserId>,
|
||||
pub platform_mac: bool,
|
||||
pub platform_linux: bool,
|
||||
pub platform_windows: bool,
|
||||
pub platform_unknown: bool,
|
||||
pub editor_features: Option<Vec<String>>,
|
||||
pub programming_languages: Option<Vec<String>>,
|
||||
pub added_to_mailing_list: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -1,4 +1,4 @@
|
||||
use super::UserId;
|
||||
use crate::db::UserId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
@ -1,4 +1,4 @@
|
||||
use super::ProjectId;
|
||||
use crate::db::ProjectId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
120
crates/collab/src/db/test_db.rs
Normal file
120
crates/collab/src/db/test_db.rs
Normal file
@ -0,0 +1,120 @@
|
||||
use super::*;
|
||||
use gpui::executor::Background;
|
||||
use parking_lot::Mutex;
|
||||
use sea_orm::ConnectionTrait;
|
||||
use sqlx::migrate::MigrateDatabase;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct TestDb {
|
||||
pub db: Option<Arc<Database>>,
|
||||
pub connection: Option<sqlx::AnyConnection>,
|
||||
}
|
||||
|
||||
impl TestDb {
|
||||
pub fn sqlite(background: Arc<Background>) -> Self {
|
||||
let url = format!("sqlite::memory:");
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut db = runtime.block_on(async {
|
||||
let mut options = ConnectOptions::new(url);
|
||||
options.max_connections(5);
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let sql = include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/migrations.sqlite/20221109000000_test_schema.sql"
|
||||
));
|
||||
db.pool
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
db.pool.get_database_backend(),
|
||||
sql.into(),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
db.runtime = Some(runtime);
|
||||
|
||||
Self {
|
||||
db: Some(Arc::new(db)),
|
||||
connection: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn postgres(background: Arc<Background>) -> Self {
|
||||
static LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
let _guard = LOCK.lock();
|
||||
let mut rng = StdRng::from_entropy();
|
||||
let url = format!(
|
||||
"postgres://postgres@localhost/zed-test-{}",
|
||||
rng.gen::<u128>()
|
||||
);
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let mut db = runtime.block_on(async {
|
||||
sqlx::Postgres::create_database(&url)
|
||||
.await
|
||||
.expect("failed to create test db");
|
||||
let mut options = ConnectOptions::new(url);
|
||||
options
|
||||
.max_connections(5)
|
||||
.idle_timeout(Duration::from_secs(0));
|
||||
let db = Database::new(options, Executor::Deterministic(background))
|
||||
.await
|
||||
.unwrap();
|
||||
let migrations_path = concat!(env!("CARGO_MANIFEST_DIR"), "/migrations");
|
||||
db.migrate(Path::new(migrations_path), false).await.unwrap();
|
||||
db
|
||||
});
|
||||
|
||||
db.runtime = Some(runtime);
|
||||
|
||||
Self {
|
||||
db: Some(Arc::new(db)),
|
||||
connection: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn db(&self) -> &Arc<Database> {
|
||||
self.db.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestDb {
|
||||
fn drop(&mut self) {
|
||||
let db = self.db.take().unwrap();
|
||||
if let sea_orm::DatabaseBackend::Postgres = db.pool.get_database_backend() {
|
||||
db.runtime.as_ref().unwrap().block_on(async {
|
||||
use util::ResultExt;
|
||||
let query = "
|
||||
SELECT pg_terminate_backend(pg_stat_activity.pid)
|
||||
FROM pg_stat_activity
|
||||
WHERE
|
||||
pg_stat_activity.datname = current_database() AND
|
||||
pid <> pg_backend_pid();
|
||||
";
|
||||
db.pool
|
||||
.execute(sea_orm::Statement::from_string(
|
||||
db.pool.get_database_backend(),
|
||||
query.into(),
|
||||
))
|
||||
.await
|
||||
.log_err();
|
||||
sqlx::Postgres::drop_database(db.options.get_url())
|
||||
.await
|
||||
.log_err();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
db::{NewUserParams, TestDb, UserId},
|
||||
db::{test_db::TestDb, NewUserParams, UserId},
|
||||
executor::Executor,
|
||||
rpc::{Server, CLEANUP_TIMEOUT},
|
||||
AppState,
|
||||
|
Loading…
Reference in New Issue
Block a user