scufflecloud_video_api/services/
stream.rs1use db_types::models::{Stream, StreamId};
2use db_types::schema::streams;
3use diesel::{ExpressionMethods, SelectableHelper};
4use diesel_async::RunQueryDsl;
5use ext_traits::{OptionExt, RequestExt, ResultExt};
6use petname::Generator;
7use tonic_types::ErrorDetails;
8
9use crate::services::VideoApiSvc;
10
11#[tonic::async_trait]
12impl<G: video_api_traits::Global> pb::scufflecloud::video::api::v1::stream_service_server::StreamService for VideoApiSvc<G> {
13 async fn create(
14 &self,
15 req: tonic::Request<pb::scufflecloud::video::api::v1::StreamCreateRequest>,
16 ) -> Result<tonic::Response<pb::scufflecloud::video::api::v1::StreamCreateResponse>, tonic::Status> {
17 let global = req.global::<G>()?;
18
19 let payload = req.into_inner();
20 let project_id = payload
21 .project_id
22 .parse()
23 .into_tonic_err_with_field_violation("project_id", "invalid ID")?;
24
25 let name = payload
28 .name
29 .or_else(|| petname::Petnames::large().generate_one(3, "-"))
30 .into_tonic_internal_err("failed to generate random stream name")?;
31
32 let stream = Stream {
33 id: StreamId::new(),
34 project_id,
35 name,
36 };
37
38 let mut conn = global
39 .db()
40 .await
41 .into_tonic_internal_err("failed to get database connection")?;
42
43 diesel::insert_into(streams::dsl::streams)
44 .values(&stream)
45 .execute(&mut conn)
46 .await
47 .into_tonic_internal_err("failed to insert stream into database")?;
48
49 Ok(tonic::Response::new(pb::scufflecloud::video::api::v1::StreamCreateResponse {
50 stream: Some(stream.into()),
51 }))
52 }
53
54 async fn get(
55 &self,
56 req: tonic::Request<pb::scufflecloud::video::api::v1::StreamGetRequest>,
57 ) -> Result<tonic::Response<pb::scufflecloud::video::api::v1::StreamGetResponse>, tonic::Status> {
58 let global = req.global::<G>()?;
59 let payload = req.into_inner();
60 let stream_id = payload.id.parse().into_tonic_err_with_field_violation("id", "invalid ID")?;
61
62 let stream = global
65 .stream_loader()
66 .load(stream_id)
67 .await
68 .ok()
69 .into_tonic_internal_err("failed to load stream")?
70 .into_tonic_err(tonic::Code::NotFound, "stream not found", ErrorDetails::new())?;
71
72 Ok(tonic::Response::new(pb::scufflecloud::video::api::v1::StreamGetResponse {
73 stream: Some(stream.into()),
74 }))
75 }
76
77 async fn update(
78 &self,
79 _req: tonic::Request<pb::scufflecloud::video::api::v1::StreamUpdateRequest>,
80 ) -> Result<tonic::Response<pb::scufflecloud::video::api::v1::StreamUpdateResponse>, tonic::Status> {
81 Err(tonic::Status::unimplemented("not implemented yet"))
82 }
83
84 async fn delete(
85 &self,
86 req: tonic::Request<pb::scufflecloud::video::api::v1::StreamDeleteRequest>,
87 ) -> Result<tonic::Response<pb::scufflecloud::video::api::v1::StreamDeleteResponse>, tonic::Status> {
88 let global = req.global::<G>()?;
89
90 let payload = req.into_inner();
91 let stream_id: StreamId = payload.id.parse().into_tonic_err_with_field_violation("id", "invalid ID")?;
92
93 let mut conn = global
96 .db()
97 .await
98 .into_tonic_internal_err("failed to get database connection")?;
99
100 let stream = diesel::delete(streams::dsl::streams)
101 .filter(streams::dsl::id.eq(stream_id))
102 .returning(Stream::as_returning())
103 .get_result::<Stream>(&mut conn)
104 .await
105 .into_tonic_internal_err("failed to insert stream into database")?;
106
107 Ok(tonic::Response::new(pb::scufflecloud::video::api::v1::StreamDeleteResponse {
108 stream: Some(stream.into()),
109 }))
110 }
111
112 async fn list(
113 &self,
114 _req: tonic::Request<pb::scufflecloud::video::api::v1::StreamListRequest>,
115 ) -> Result<tonic::Response<pb::scufflecloud::video::api::v1::StreamListResponse>, tonic::Status> {
116 Err(tonic::Status::unimplemented("not implemented yet"))
117 }
118}