1use monsta_proto::{
2 monsta_server::{Monsta, MonstaServer},
3 *,
4};
5use tonic::{Request as TonicRequest, Response as TonicResponse};
6
7use crate::{database::Database, universe::Universe, Error, Result};
8
9type TonicResult<T> = std::result::Result<T, tonic::Status>;
10
11pub struct Server {
12 uv: Universe,
13}
14
15#[tonic::async_trait]
16impl Monsta for Server {
17 async fn call(&self, request: TonicRequest<Request>) -> TonicResult<TonicResponse<Response>> {
18 let req = request.into_inner();
19 if let Some(req) = req.database {
20 let res = self.handle_database(req).await?;
21 Ok(TonicResponse::new(Response {
22 database: Some(res),
23 ..Default::default()
24 }))
25 } else if let Some(req) = req.collection {
26 let res = self.handle_collection(req).await?;
27 Ok(TonicResponse::new(Response {
28 collection: Some(res),
29 ..Default::default()
30 }))
31 } else if let Some(req) = req.transaction {
32 let res = self.handle_transaction(req).await?;
33 Ok(TonicResponse::new(Response {
34 transaction: Some(res),
35 ..Default::default()
36 }))
37 } else {
38 Err(Error::InvalidArgument("missing request".to_owned()).into())
39 }
40 }
41}
42
43impl Server {
44 pub fn new() -> MonstaServer<Server> {
45 let server = Server {
46 uv: Universe::new(),
47 };
48 MonstaServer::new(server)
49 }
50}
51
52impl Server {
53 async fn handle_database(&self, req: DatabaseRequest) -> Result<DatabaseResponse> {
54 if let Some(req) = req.create_database {
55 let res = self.handle_create_database(req).await?;
56 Ok(DatabaseResponse {
57 create_database: Some(res),
58 ..Default::default()
59 })
60 } else if let Some(req) = req.describe_database {
61 let res = self.handle_describe_database(req).await?;
62 Ok(DatabaseResponse {
63 describe_database: Some(res),
64 ..Default::default()
65 })
66 } else {
67 Err(Error::InvalidArgument(
68 "unknown database request".to_owned(),
69 ))
70 }
71 }
72
73 async fn handle_create_database(
74 &self,
75 req: CreateDatabaseRequest,
76 ) -> Result<CreateDatabaseResponse> {
77 let spec = req
78 .spec
79 .ok_or_else(|| Error::InvalidArgument("missing database specification".to_owned()))?;
80 let db = self.uv.create_database(spec).await?;
81 let desc = db.desc().await;
82 Ok(CreateDatabaseResponse { desc: Some(desc) })
83 }
84
85 async fn handle_describe_database(
86 &self,
87 req: DescribeDatabaseRequest,
88 ) -> Result<DescribeDatabaseResponse> {
89 if req.id > 0 {
90 let db = self
91 .uv
92 .database(req.id)
93 .await
94 .ok_or_else(|| Error::NotFound(format!("database id {}", req.id)))?;
95 let desc = db.desc().await;
96 Ok(DescribeDatabaseResponse { desc: Some(desc) })
97 } else if !req.name.is_empty() {
98 let db = self
99 .uv
100 .lookup_database(&req.name)
101 .await
102 .ok_or_else(|| Error::NotFound(format!("database name {}", req.name)))?;
103 let desc = db.desc().await;
104 Ok(DescribeDatabaseResponse { desc: Some(desc) })
105 } else {
106 Err(Error::InvalidArgument(
107 "missing database id or name".to_owned(),
108 ))
109 }
110 }
111
112 async fn handle_collection(&self, req: CollectionRequest) -> Result<CollectionResponse> {
113 let db = self
114 .uv
115 .database(req.database_id)
116 .await
117 .ok_or_else(|| Error::NotFound(format!("database id {}", req.database_id)))?;
118 if let Some(req) = req.create_collection {
119 let res = self.handle_create_collection(db, req).await?;
120 Ok(CollectionResponse {
121 create_collection: Some(res),
122 ..Default::default()
123 })
124 } else if let Some(req) = req.describe_collection {
125 let res = self.handle_describe_collection(db, req).await?;
126 Ok(CollectionResponse {
127 describe_collection: Some(res),
128 ..Default::default()
129 })
130 } else {
131 Err(Error::InvalidArgument(
132 "unknown collection request".to_owned(),
133 ))
134 }
135 }
136
137 async fn handle_create_collection(
138 &self,
139 db: Database,
140 req: CreateCollectionRequest,
141 ) -> Result<CreateCollectionResponse> {
142 let spec = req
143 .spec
144 .ok_or_else(|| Error::InvalidArgument("missing collection specification".to_owned()))?;
145 let co = db.create_collection(spec).await?;
146 let desc = co.desc().await;
147 Ok(CreateCollectionResponse { desc: Some(desc) })
148 }
149
150 async fn handle_describe_collection(
151 &self,
152 db: Database,
153 req: DescribeCollectionRequest,
154 ) -> Result<DescribeCollectionResponse> {
155 if req.id > 0 {
156 let co = db
157 .collection(req.id)
158 .await
159 .ok_or_else(|| Error::NotFound(format!("collection id {}", req.id)))?;
160 let desc = co.desc().await;
161 Ok(DescribeCollectionResponse { desc: Some(desc) })
162 } else if !req.name.is_empty() {
163 let co = db
164 .lookup_collection(&req.name)
165 .await
166 .ok_or_else(|| Error::NotFound(format!("collection name {}", req.name)))?;
167 let desc = co.desc().await;
168 Ok(DescribeCollectionResponse { desc: Some(desc) })
169 } else {
170 Err(Error::InvalidArgument(
171 "missing collection id or name".to_owned(),
172 ))
173 }
174 }
175
176 async fn handle_transaction(&self, req: DatabaseTxnRequest) -> Result<DatabaseTxnResponse> {
177 let db = self
178 .uv
179 .database(req.database_id)
180 .await
181 .ok_or_else(|| Error::NotFound(format!("database id {}", req.database_id)))?;
182 db.execute_transaction(req).await
183 }
184}