monsta_server/
server.rs

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}