WIP: pass synchronize channel buffers integration test

This commit is contained in:
Mikayla 2023-08-21 17:53:37 -07:00
parent a7a4e2e369
commit 364ed1f840
No known key found for this signature in database
15 changed files with 411 additions and 135 deletions

View file

@ -124,3 +124,4 @@ id_type!(ReplicaId);
id_type!(ServerId);
id_type!(SignupId);
id_type!(UserId);
id_type!(ChannelBufferCollaboratorId);

View file

@ -1,20 +1,12 @@
use super::*;
use prost::Message;
pub struct Buffer {
pub struct ChannelBuffer {
pub base_text: String,
pub operations: Vec<proto::Operation>,
}
impl Database {
pub async fn create_buffer(&self) -> Result<BufferId> {
self.transaction(|tx| async move {
let buffer = buffer::ActiveModel::new().insert(&*tx).await?;
Ok(buffer.id)
})
.await
}
pub async fn update_buffer(
&self,
buffer_id: BufferId,
@ -69,13 +61,65 @@ impl Database {
.await
}
pub async fn get_buffer(&self, id: BufferId) -> Result<Buffer> {
pub async fn join_buffer_for_channel(
&self,
channel_id: ChannelId,
user_id: UserId,
connection: ConnectionId,
) -> Result<ChannelBuffer> {
self.transaction(|tx| async move {
let buffer = buffer::Entity::find_by_id(id)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("no such buffer"))?;
let tx = tx;
// Get or create buffer from channel
self.check_user_is_channel_member(channel_id, user_id, &tx)
.await?;
let buffer = channel::Model {
id: channel_id,
..Default::default()
}
.find_related(buffer::Entity)
.one(&*tx)
.await?;
let buffer = if let Some(buffer) = buffer {
buffer
} else {
let buffer = buffer::ActiveModel {
channel_id: ActiveValue::Set(channel_id),
..Default::default()
}
.insert(&*tx)
.await?;
buffer
};
// Join the collaborators
let collaborators = buffer
.find_related(channel_buffer_collaborator::Entity)
.all(&*tx)
.await?;
let replica_ids = collaborators
.iter()
.map(|c| c.replica_id)
.collect::<HashSet<_>>();
let mut replica_id = ReplicaId(0);
while replica_ids.contains(&replica_id) {
replica_id.0 += 1;
}
channel_buffer_collaborator::ActiveModel {
buffer_id: ActiveValue::Set(buffer.id),
connection_id: ActiveValue::Set(connection.id as i32),
connection_server_id: ActiveValue::Set(ServerId(connection.owner_id as i32)),
user_id: ActiveValue::Set(user_id),
replica_id: ActiveValue::Set(replica_id),
..Default::default()
}
.insert(&*tx)
.await?;
// Assemble the buffer state
let id = buffer.id;
let base_text = if buffer.epoch > 0 {
buffer_snapshot::Entity::find()
.filter(
@ -128,13 +172,44 @@ impl Database {
})
}
Ok(Buffer {
Ok(ChannelBuffer {
base_text,
operations,
})
})
.await
}
pub async fn get_buffer_collaborators(&self, buffer: BufferId) -> Result<()> {
todo!()
}
pub async fn leave_buffer(&self, buffer: BufferId, user: UserId) -> Result<()> {
self.transaction(|tx| async move {
//TODO
// let tx = tx;
// let channel = channel::Entity::find_by_id(channel_id)
// .one(&*tx)
// .await?
// .ok_or_else(|| anyhow!("invalid channel"))?;
// if let Some(id) = channel.main_buffer_id {
// return Ok(id);
// } else {
// let buffer = buffer::ActiveModel::new().insert(&*tx).await?;
// channel::ActiveModel {
// id: ActiveValue::Unchanged(channel_id),
// main_buffer_id: ActiveValue::Set(Some(buffer.id)),
// ..Default::default()
// }
// .update(&*tx)
// .await?;
// Ok(buffer.id)
// }
Ok(())
})
.await
}
}
mod storage {

View file

@ -689,34 +689,6 @@ impl Database {
})
.await
}
pub async fn get_or_create_buffer_for_channel(
&self,
channel_id: ChannelId,
) -> Result<BufferId> {
self.transaction(|tx| async move {
let tx = tx;
let channel = channel::Entity::find_by_id(channel_id)
.one(&*tx)
.await?
.ok_or_else(|| anyhow!("invalid channel"))?;
if let Some(id) = channel.main_buffer_id {
return Ok(id);
} else {
let buffer = buffer::ActiveModel::new().insert(&*tx).await?;
channel::ActiveModel {
id: ActiveValue::Unchanged(channel_id),
main_buffer_id: ActiveValue::Set(Some(buffer.id)),
..Default::default()
}
.update(&*tx)
.await?;
Ok(buffer.id)
}
})
.await
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]

View file

@ -3,6 +3,7 @@ pub mod buffer;
pub mod buffer_operation;
pub mod buffer_snapshot;
pub mod channel;
pub mod channel_buffer_collaborator;
pub mod channel_member;
pub mod channel_path;
pub mod contact;

View file

@ -1,4 +1,4 @@
use crate::db::BufferId;
use crate::db::{BufferId, ChannelId};
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
@ -7,6 +7,7 @@ pub struct Model {
#[sea_orm(primary_key)]
pub id: BufferId,
pub epoch: i32,
pub channel_id: ChannelId,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
@ -15,6 +16,14 @@ pub enum Relation {
Operations,
#[sea_orm(has_many = "super::buffer_snapshot::Entity")]
Snapshots,
#[sea_orm(
belongs_to = "super::channel::Entity",
from = "Column::ChannelId",
to = "super::channel::Column::Id"
)]
Channel,
#[sea_orm(has_many = "super::channel_buffer_collaborator::Entity")]
Collaborators,
}
impl Related<super::buffer_operation::Entity> for Entity {
@ -29,4 +38,16 @@ impl Related<super::buffer_snapshot::Entity> for Entity {
}
}
impl Related<super::channel::Entity> for Entity {
fn to() -> RelationDef {
Relation::Channel.def()
}
}
impl Related<super::channel_buffer_collaborator::Entity> for Entity {
fn to() -> RelationDef {
Relation::Collaborators.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View file

@ -7,7 +7,6 @@ pub struct Model {
#[sea_orm(primary_key)]
pub id: ChannelId,
pub name: String,
pub main_buffer_id: Option<BufferId>,
}
impl ActiveModelBehavior for ActiveModel {}
@ -16,6 +15,8 @@ impl ActiveModelBehavior for ActiveModel {}
pub enum Relation {
#[sea_orm(has_one = "super::room::Entity")]
Room,
#[sea_orm(has_one = "super::room::Entity")]
Buffer,
#[sea_orm(has_many = "super::channel_member::Entity")]
Member,
}
@ -31,3 +32,9 @@ impl Related<super::room::Entity> for Entity {
Relation::Room.def()
}
}
impl Related<super::buffer::Entity> for Entity {
fn to() -> RelationDef {
Relation::Buffer.def()
}
}

View file

@ -0,0 +1,42 @@
use crate::db::{BufferId, ChannelBufferCollaboratorId, ReplicaId, ServerId, UserId};
use rpc::ConnectionId;
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "channel_buffer_collaborators")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: ChannelBufferCollaboratorId,
pub buffer_id: BufferId,
pub connection_id: i32,
pub connection_server_id: ServerId,
pub user_id: UserId,
pub replica_id: ReplicaId,
}
impl Model {
pub fn connection(&self) -> ConnectionId {
ConnectionId {
owner_id: self.connection_server_id.0 as u32,
id: self.connection_id as u32,
}
}
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::buffer::Entity",
from = "Column::BufferId",
to = "super::buffer::Column::Id"
)]
Buffer,
}
impl Related<super::buffer::Entity> for Entity {
fn to() -> RelationDef {
Relation::Buffer.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View file

@ -6,7 +6,60 @@ use text::Buffer;
test_both_dbs!(test_buffers, test_buffers_postgres, test_buffers_sqlite);
async fn test_buffers(db: &Arc<Database>) {
let buffer_id = db.create_buffer().await.unwrap();
// Prep database test info
let a_id = db
.create_user(
"user_a@example.com",
false,
NewUserParams {
github_login: "user_a".into(),
github_user_id: 101,
invite_count: 0,
},
)
.await
.unwrap()
.user_id;
let b_id = db
.create_user(
"user_b@example.com",
false,
NewUserParams {
github_login: "user_b".into(),
github_user_id: 102,
invite_count: 0,
},
)
.await
.unwrap()
.user_id;
// This user will not be a part of the channel
let c_id = db
.create_user(
"user_b@example.com",
false,
NewUserParams {
github_login: "user_b".into(),
github_user_id: 102,
invite_count: 0,
},
)
.await
.unwrap()
.user_id;
let zed_id = db.create_root_channel("zed", "1", a_id).await.unwrap();
db.invite_channel_member(zed_id, b_id, a_id, false)
.await
.unwrap();
db.respond_to_channel_invite(zed_id, b_id, true)
.await
.unwrap();
// TODO: Join buffer
let buffer_id = db.get_or_create_buffer_for_channel(zed_id);
let mut buffer = Buffer::new(0, 0, "".to_string());
let mut operations = Vec::new();
@ -23,7 +76,7 @@ async fn test_buffers(db: &Arc<Database>) {
db.update_buffer(buffer_id, &operations).await.unwrap();
let buffer_data = db.get_buffer(buffer_id).await.unwrap();
let buffer_data = db.open_buffer(buffer_id).await.unwrap();
let mut buffer_2 = Buffer::new(0, 0, buffer_data.base_text);
buffer_2