WIP: Channel CRUD
This commit is contained in:
parent
bb70901e71
commit
26a94b5244
4 changed files with 163 additions and 128 deletions
|
@ -191,13 +191,13 @@ CREATE TABLE "channels" (
|
||||||
"name" VARCHAR NOT NULL,
|
"name" VARCHAR NOT NULL,
|
||||||
"room_id" INTEGER REFERENCES rooms (id) ON DELETE SET NULL,
|
"room_id" INTEGER REFERENCES rooms (id) ON DELETE SET NULL,
|
||||||
"created_at" TIMESTAMP NOT NULL DEFAULT now
|
"created_at" TIMESTAMP NOT NULL DEFAULT now
|
||||||
)
|
);
|
||||||
|
|
||||||
CREATE TABLE "channel_parents" (
|
CREATE TABLE "channel_parents" (
|
||||||
"child_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
"child_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||||
"parent_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
"parent_id" INTEGER NOT NULL REFERENCES channels (id) ON DELETE CASCADE,
|
||||||
PRIMARY KEY(child_id, parent_id)
|
PRIMARY KEY(child_id, parent_id)
|
||||||
)
|
);
|
||||||
|
|
||||||
-- CREATE UNIQUE INDEX "index_channels_on_id_path" ON "channels" ("id_path");
|
-- CREATE UNIQUE INDEX "index_channels_on_id_path" ON "channels" ("id_path");
|
||||||
|
|
||||||
|
@ -207,6 +207,6 @@ CREATE TABLE "channel_members" (
|
||||||
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
"user_id" INTEGER NOT NULL REFERENCES users (id) ON DELETE CASCADE,
|
||||||
"admin" BOOLEAN NOT NULL DEFAULT false,
|
"admin" BOOLEAN NOT NULL DEFAULT false,
|
||||||
"updated_at" TIMESTAMP NOT NULL DEFAULT now
|
"updated_at" TIMESTAMP NOT NULL DEFAULT now
|
||||||
)
|
);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX "index_channel_members_on_channel_id_and_user_id" ON "channel_members" ("channel_id", "user_id");
|
CREATE UNIQUE INDEX "index_channel_members_on_channel_id_and_user_id" ON "channel_members" ("channel_id", "user_id");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
mod access_token;
|
mod access_token;
|
||||||
mod channel;
|
mod channel;
|
||||||
mod channel_member;
|
mod channel_member;
|
||||||
mod channel_parent;
|
// mod channel_parent;
|
||||||
mod contact;
|
mod contact;
|
||||||
mod follower;
|
mod follower;
|
||||||
mod language_server;
|
mod language_server;
|
||||||
|
@ -3032,134 +3032,167 @@ impl Database {
|
||||||
|
|
||||||
// channels
|
// channels
|
||||||
|
|
||||||
pub async fn get_channels(&self, user_id: UserId) -> Result<Vec<ChannelId>> {
|
pub async fn create_channel(&self, name: &str) -> Result<ChannelId> {
|
||||||
|
self.transaction(move |tx| async move {
|
||||||
|
let tx = tx;
|
||||||
|
|
||||||
|
let channel = channel::ActiveModel {
|
||||||
|
name: ActiveValue::Set(name.to_string()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let channel = channel.insert(&*tx).await?;
|
||||||
|
|
||||||
|
Ok(channel.id)
|
||||||
|
}).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_channel_member(&self, channel_id: ChannelId, user_id: UserId) -> Result<()> {
|
||||||
|
self.transaction(move |tx| async move {
|
||||||
|
let tx = tx;
|
||||||
|
|
||||||
|
let channel_membership = channel_member::ActiveModel {
|
||||||
|
channel_id: ActiveValue::Set(channel_id),
|
||||||
|
user_id: ActiveValue::Set(user_id),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
channel_membership.insert(&*tx).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_channels(&self, user_id: UserId) -> Vec<ChannelId> {
|
||||||
self.transaction(|tx| async move {
|
self.transaction(|tx| async move {
|
||||||
let tx = tx;
|
let tx = tx;
|
||||||
|
|
||||||
let user = user::Model {
|
|
||||||
id: user_id,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let mut channel_ids = user
|
|
||||||
.find_related(channel_member::Entity)
|
|
||||||
.select_only()
|
|
||||||
.column(channel_member::Column::ChannelId)
|
|
||||||
.all(&*tx)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let descendants = Alias::new("descendants");
|
|
||||||
let cte_referencing = SelectStatement::new()
|
|
||||||
.column(channel_parent::Column::ChildId)
|
|
||||||
.from(channel::Entity)
|
|
||||||
.and_where(
|
|
||||||
Expr::col(channel_parent::Column::ParentId)
|
|
||||||
.in_subquery(SelectStatement::new().from(descendants).take())
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
WITH RECURSIVE descendant_ids(id) AS (
|
|
||||||
$1
|
|
||||||
UNION ALL
|
|
||||||
SELECT child_id as id FROM channel_parents WHERE parent_id IN descendants
|
|
||||||
)
|
|
||||||
SELECT * from channels where id in descendant_ids
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// WITH RECURSIVE descendants(id) AS (
|
|
||||||
// // SQL QUERY FOR SELECTING Initial IDs
|
|
||||||
// UNION
|
|
||||||
// SELECT id FROM ancestors WHERE p.parent = id
|
|
||||||
// )
|
|
||||||
// SELECT * FROM descendants;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let descendant_channel_ids =
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let query = sea_query::Query::with().recursive(true);
|
|
||||||
|
|
||||||
|
|
||||||
for id_path in id_paths {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// zed/public/plugins
|
|
||||||
// zed/public/plugins/js
|
|
||||||
// zed/zed-livekit
|
|
||||||
// livekit/zed-livekit
|
|
||||||
// zed - 101
|
|
||||||
// livekit - 500
|
|
||||||
// zed-livekit - 510
|
|
||||||
// public - 150
|
|
||||||
// plugins - 200
|
|
||||||
// js - 300
|
|
||||||
//
|
|
||||||
// Channel, Parent - edges
|
|
||||||
// 510 - 500
|
|
||||||
// 510 - 101
|
|
||||||
//
|
|
||||||
// Given the channel 'Zed' (101)
|
|
||||||
// Select * from EDGES where parent = 101 => 510
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
"SELECT * from channels where id_path like '$1?'"
|
|
||||||
|
|
||||||
// https://www.postgresql.org/docs/current/queries-with.html
|
|
||||||
// https://www.sqlite.org/lang_with.html
|
|
||||||
|
|
||||||
"SELECT channel_id from channel_ancestors where ancestor_id IN $()"
|
|
||||||
|
|
||||||
// | channel_id | ancestor_ids |
|
|
||||||
// 150 150
|
|
||||||
// 150 101
|
|
||||||
// 200 101
|
|
||||||
// 300 101
|
|
||||||
// 200 150
|
|
||||||
// 300 150
|
|
||||||
// 300 200
|
|
||||||
//
|
|
||||||
// // | channel_id | ancestor_ids |
|
|
||||||
// 150 101
|
|
||||||
// 200 101
|
|
||||||
// 300 101
|
|
||||||
// 200 150
|
|
||||||
// 300 [150, 200]
|
|
||||||
|
|
||||||
channel::Entity::find()
|
|
||||||
.filter(channel::Column::IdPath.like(id_paths.unwrap()))
|
|
||||||
|
|
||||||
dbg!(&id_paths.unwrap()[0].id_path);
|
|
||||||
|
|
||||||
// let mut channel_members_by_channel_id = HashMap::new();
|
|
||||||
// for channel_member in channel_members {
|
|
||||||
// channel_members_by_channel_id
|
|
||||||
// .entry(channel_member.channel_id)
|
|
||||||
// .or_insert_with(Vec::new)
|
|
||||||
// .push(channel_member);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut channel_messages = channel_message::Entity::find()
|
|
||||||
// .filter(channel_message::Column::ChannelId.in_selection(channel_ids))
|
|
||||||
// .all(&*tx)
|
|
||||||
// .await?;
|
|
||||||
|
|
||||||
// let mut channel_messages_by_channel_id = HashMap::new();
|
|
||||||
// for channel_message in channel_messages {
|
|
||||||
// channel_messages_by_channel_id
|
|
||||||
// .entry(channel_message.channel_id)
|
|
||||||
// .or_insert_with(Vec::new)
|
|
||||||
// .push(channel_message);
|
|
||||||
// }
|
|
||||||
|
|
||||||
todo!();
|
|
||||||
// Ok(channels)
|
|
||||||
})
|
})
|
||||||
.await
|
// let user = user::Model {
|
||||||
|
// id: user_id,
|
||||||
|
// ..Default::default()
|
||||||
|
// };
|
||||||
|
// let mut channel_ids = user
|
||||||
|
// .find_related(channel_member::Entity)
|
||||||
|
// .select_only()
|
||||||
|
// .column(channel_member::Column::ChannelId)
|
||||||
|
// .all(&*tx)
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
// // let descendants = Alias::new("descendants");
|
||||||
|
// // let cte_referencing = SelectStatement::new()
|
||||||
|
// // .column(channel_parent::Column::ChildId)
|
||||||
|
// // .from(channel::Entity)
|
||||||
|
// // .and_where(
|
||||||
|
// // Expr::col(channel_parent::Column::ParentId)
|
||||||
|
// // .in_subquery(SelectStatement::new().from(descendants).take())
|
||||||
|
// // );
|
||||||
|
|
||||||
|
// // /*
|
||||||
|
// // WITH RECURSIVE descendant_ids(id) AS (
|
||||||
|
// // $1
|
||||||
|
// // UNION ALL
|
||||||
|
// // SELECT child_id as id FROM channel_parents WHERE parent_id IN descendants
|
||||||
|
// // )
|
||||||
|
// // SELECT * from channels where id in descendant_ids
|
||||||
|
// // */
|
||||||
|
|
||||||
|
|
||||||
|
// // // WITH RECURSIVE descendants(id) AS (
|
||||||
|
// // // // SQL QUERY FOR SELECTING Initial IDs
|
||||||
|
// // // UNION
|
||||||
|
// // // SELECT id FROM ancestors WHERE p.parent = id
|
||||||
|
// // // )
|
||||||
|
// // // SELECT * FROM descendants;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // // let descendant_channel_ids =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // // let query = sea_query::Query::with().recursive(true);
|
||||||
|
|
||||||
|
|
||||||
|
// // for id_path in id_paths {
|
||||||
|
// // //
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
// // // zed/public/plugins
|
||||||
|
// // // zed/public/plugins/js
|
||||||
|
// // // zed/zed-livekit
|
||||||
|
// // // livekit/zed-livekit
|
||||||
|
// // // zed - 101
|
||||||
|
// // // livekit - 500
|
||||||
|
// // // zed-livekit - 510
|
||||||
|
// // // public - 150
|
||||||
|
// // // plugins - 200
|
||||||
|
// // // js - 300
|
||||||
|
// // //
|
||||||
|
// // // Channel, Parent - edges
|
||||||
|
// // // 510 - 500
|
||||||
|
// // // 510 - 101
|
||||||
|
// // //
|
||||||
|
// // // Given the channel 'Zed' (101)
|
||||||
|
// // // Select * from EDGES where parent = 101 => 510
|
||||||
|
// // //
|
||||||
|
|
||||||
|
|
||||||
|
// // "SELECT * from channels where id_path like '$1?'"
|
||||||
|
|
||||||
|
// // // https://www.postgresql.org/docs/current/queries-with.html
|
||||||
|
// // // https://www.sqlite.org/lang_with.html
|
||||||
|
|
||||||
|
// // "SELECT channel_id from channel_ancestors where ancestor_id IN $()"
|
||||||
|
|
||||||
|
// // // | channel_id | ancestor_ids |
|
||||||
|
// // // 150 150
|
||||||
|
// // // 150 101
|
||||||
|
// // // 200 101
|
||||||
|
// // // 300 101
|
||||||
|
// // // 200 150
|
||||||
|
// // // 300 150
|
||||||
|
// // // 300 200
|
||||||
|
// // //
|
||||||
|
// // // // | channel_id | ancestor_ids |
|
||||||
|
// // // 150 101
|
||||||
|
// // // 200 101
|
||||||
|
// // // 300 101
|
||||||
|
// // // 200 150
|
||||||
|
// // // 300 [150, 200]
|
||||||
|
|
||||||
|
// // channel::Entity::find()
|
||||||
|
// // .filter(channel::Column::IdPath.like(id_paths.unwrap()))
|
||||||
|
|
||||||
|
// // dbg!(&id_paths.unwrap()[0].id_path);
|
||||||
|
|
||||||
|
// // // let mut channel_members_by_channel_id = HashMap::new();
|
||||||
|
// // // for channel_member in channel_members {
|
||||||
|
// // // channel_members_by_channel_id
|
||||||
|
// // // .entry(channel_member.channel_id)
|
||||||
|
// // // .or_insert_with(Vec::new)
|
||||||
|
// // // .push(channel_member);
|
||||||
|
// // // }
|
||||||
|
|
||||||
|
// // // let mut channel_messages = channel_message::Entity::find()
|
||||||
|
// // // .filter(channel_message::Column::ChannelId.in_selection(channel_ids))
|
||||||
|
// // // .all(&*tx)
|
||||||
|
// // // .await?;
|
||||||
|
|
||||||
|
// // // let mut channel_messages_by_channel_id = HashMap::new();
|
||||||
|
// // // for channel_message in channel_messages {
|
||||||
|
// // // channel_messages_by_channel_id
|
||||||
|
// // // .entry(channel_message.channel_id)
|
||||||
|
// // // .or_insert_with(Vec::new)
|
||||||
|
// // // .push(channel_message);
|
||||||
|
// // // }
|
||||||
|
|
||||||
|
// // todo!();
|
||||||
|
// // // Ok(channels)
|
||||||
|
// Err(Error("not implemented"))
|
||||||
|
// })
|
||||||
|
// .await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn transaction<F, Fut, T>(&self, f: F) -> Result<T>
|
async fn transaction<F, Fut, T>(&self, f: F) -> Result<T>
|
||||||
|
|
|
@ -6,6 +6,7 @@ use sea_orm::entity::prelude::*;
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key)]
|
#[sea_orm(primary_key)]
|
||||||
pub id: ChannelId,
|
pub id: ChannelId,
|
||||||
|
pub name: String,
|
||||||
pub room_id: Option<RoomId>,
|
pub room_id: Option<RoomId>,
|
||||||
// pub id_path: String,
|
// pub id_path: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ use workspace::Workspace;
|
||||||
|
|
||||||
mod integration_tests;
|
mod integration_tests;
|
||||||
mod randomized_integration_tests;
|
mod randomized_integration_tests;
|
||||||
|
mod channel_tests;
|
||||||
|
|
||||||
struct TestServer {
|
struct TestServer {
|
||||||
app_state: Arc<AppState>,
|
app_state: Arc<AppState>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue