Skip to content

Commit 61e286e

Browse files
committed
refactor
1 parent b87eb47 commit 61e286e

File tree

11 files changed

+111
-89
lines changed

11 files changed

+111
-89
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ redis = { version = "0.25.3", default-features = false, features = [
1818
] }
1919
serde = { version = "1.0.163", features = ["derive"] }
2020
serde_json = "1.0.96"
21+
thiserror = "1.0.60"
2122
tokio = "1.28.1"
2223
url = "2.3.1"
2324
vercel_runtime = "1.1.1"

api/collections.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ async fn handler_post(req: Request) -> Result<Response<Body>, Error> {
2929
Err(err) => internal_server_error(format!("failed creating collection: {err}")));
3030

3131
Ok(Response::builder()
32-
.status(StatusCode::OK)
32+
.status(StatusCode::CREATED)
3333
.header("content-type", "application/json")
3434
.body(Body::Text(serde_json::to_string(&res).unwrap()))?)
3535
}

api/collections/[collectionid].rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use example_rest_api::{
2-
controller::Controller, expect, get_path_param, method_handlers, utils::response::no_content,
2+
controller::{errors::Error as ControllerError, Controller},
3+
expect, get_path_param, method_handlers,
4+
utils::response::no_content,
35
};
46
use vercel_runtime::{
5-
http::{internal_server_error, not_found, ok},
7+
http::{bad_request, internal_server_error, not_found, ok},
68
*,
79
};
810

@@ -14,6 +16,7 @@ async fn main() -> Result<(), Error> {
1416
async fn handler(req: Request) -> Result<Response<Body>, Error> {
1517
method_handlers!(req,
1618
"GET" => handler_get(req).await,
19+
"PUT" => handler_put(req).await,
1720
"DELETE" => handler_delete(req).await,
1821
"OPTIONS" => no_content(),
1922
)
@@ -34,6 +37,25 @@ async fn handler_get(req: Request) -> Result<Response<Body>, Error> {
3437
}
3538
}
3639

40+
async fn handler_put(req: Request) -> Result<Response<Body>, Error> {
41+
let controller = expect!(Controller::from_env(),
42+
Err(err) => internal_server_error(format!("failed initializing controller: {err}")));
43+
44+
let collectionid = get_path_param!(&req, "collectionid");
45+
46+
let req = expect!(serde_json::from_slice(req.body()),
47+
Err(err) => bad_request(format!("failed decoding request body: {err}")));
48+
49+
let res = expect!(controller.update_collection(&collectionid, req).await,
50+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
51+
Err(err) => internal_server_error(format!("failed updating collection: {err}")));
52+
53+
Ok(Response::builder()
54+
.status(StatusCode::OK)
55+
.header("content-type", "application/json")
56+
.body(Body::Text(serde_json::to_string(&res).unwrap()))?)
57+
}
58+
3759
async fn handler_delete(req: Request) -> Result<Response<Body>, Error> {
3860
let controller = expect!(Controller::from_env(),
3961
Err(err) => internal_server_error(format!("failed initializing controller: {err}")));

api/collections/[collectionid]/objects.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use example_rest_api::{
2-
controller::{errors::ErrorKind, Controller},
2+
controller::{errors::Error as ControllerError, Controller},
33
expect, get_path_param, method_handlers,
44
utils::response::no_content,
55
};
@@ -28,11 +28,8 @@ async fn handler_get(req: Request) -> Result<Response<Body>, Error> {
2828
let collectionid = get_path_param!(&req, "collectionid");
2929

3030
let res = expect!(controller.list_objects(&collectionid).await,
31-
Err(err) => match err.kind() {
32-
ErrorKind::CollectionNotFound => not_found("collection not found"),
33-
_ => internal_server_error(format!("failed listing objects: {err}"))
34-
}
35-
);
31+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
32+
Err(err) => internal_server_error(format!("failed listing objects: {err}")));
3633

3734
ok(res)
3835
}
@@ -47,11 +44,8 @@ async fn handler_post(req: Request) -> Result<Response<Body>, Error> {
4744
Err(err) => bad_request(format!("failed decoding request body: {err}")));
4845

4946
let res = expect!(controller.create_object(&collectionid, req).await,
50-
Err(err) => match err.kind() {
51-
ErrorKind::CollectionNotFound => not_found("collection not found"),
52-
_ => internal_server_error(format!("failed creating object: {err}"))
53-
}
54-
);
47+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
48+
Err(err) => internal_server_error(format!("failed creating object: {err}")));
5549

5650
Ok(Response::builder()
5751
.status(StatusCode::CREATED)

api/collections/[collectionid]/objects/[objectid].rs

+8-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use example_rest_api::{
2-
controller::{errors::ErrorKind, Controller},
2+
controller::{errors::Error as ControllerError, Controller},
33
expect, get_path_param, method_handlers,
44
utils::response::no_content,
55
};
@@ -30,11 +30,8 @@ async fn handler_get(req: Request) -> Result<Response<Body>, Error> {
3030
let objectid = get_path_param!(&req, "objectid");
3131

3232
let res = expect!(controller.get_object(&collectionid, &objectid).await,
33-
Err(err) => match err.kind() {
34-
ErrorKind::CollectionNotFound => not_found("collection not found"),
35-
_ => internal_server_error(format!("failed getting object: {err}"))
36-
}
37-
);
33+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
34+
Err(err) => internal_server_error(format!("failed getting object: {err}")));
3835

3936
match res {
4037
None => not_found("object not found"),
@@ -53,12 +50,9 @@ async fn handler_put(req: Request) -> Result<Response<Body>, Error> {
5350
Err(err) => bad_request(format!("failed decoding request body: {err}")));
5451

5552
let res = expect!(controller.set_object(&collectionid, &objectid, req).await,
56-
Err(err) => match err.kind() {
57-
ErrorKind::CollectionNotFound => not_found("collection not found"),
58-
ErrorKind::ObjectNotFound => not_found("object not found"),
59-
_ => internal_server_error(format!("failed getting object: {err}"))
60-
}
61-
);
53+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
54+
Err(ControllerError::ObjectNotFound) => not_found("object not found"),
55+
Err(err) => internal_server_error(format!("failed getting object: {err}")));
6256

6357
ok(res)
6458
}
@@ -71,11 +65,8 @@ async fn handler_delete(req: Request) -> Result<Response<Body>, Error> {
7165
let objectid = get_path_param!(&req, "objectid");
7266

7367
expect!(controller.delete_object(&collectionid, &objectid).await,
74-
Err(err) => match err.kind() {
75-
ErrorKind::CollectionNotFound => not_found("collection not found"),
76-
_ => internal_server_error(format!("failed getting object: {err}"))
77-
}
78-
);
68+
Err(ControllerError::CollectionNotFound) => not_found("collection not found"),
69+
Err(err) => internal_server_error(format!("failed getting object: {err}")));
7970

8071
Ok(Response::builder()
8172
.status(StatusCode::NO_CONTENT)

lib/controller/collections.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use super::errors::Error;
12
use super::util::GROUP_COLLECTIONS;
23
use super::Controller;
34
use super::{errors::Result, util::build_key};
4-
use crate::models::{Collection, CollectionRequest};
5+
use crate::models::{Collection, CollectionRequest, Update};
56
use chrono::Local;
67

78
impl Controller {
@@ -34,6 +35,28 @@ impl Controller {
3435
.transpose()?)
3536
}
3637

38+
pub async fn update_collection(
39+
&self,
40+
id: &str,
41+
new_collection: <Collection as Update>::With,
42+
) -> Result<Collection> {
43+
let Some(mut collection) = self.get_collection(id).await? else {
44+
return Err(Error::CollectionNotFound);
45+
};
46+
47+
collection.update(new_collection);
48+
let serialized = serde_json::to_vec(&collection)?;
49+
self.persistence
50+
.set(
51+
&build_key(&[GROUP_COLLECTIONS, id]),
52+
&serialized,
53+
self.object_lifetime,
54+
)
55+
.await?;
56+
57+
Ok(collection)
58+
}
59+
3760
pub async fn delete_collection(&self, id: &str) -> Result<()> {
3861
let vals = self
3962
.persistence

lib/controller/errors.rs

+9-44
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,16 @@
1-
use std::fmt;
2-
31
pub type Result<T, E = Error> = core::result::Result<T, E>;
42

5-
#[derive(Debug)]
6-
pub struct Error(Box<ErrorKind>);
7-
8-
#[derive(Debug)]
9-
pub enum ErrorKind {
3+
#[derive(thiserror::Error, Debug)]
4+
pub enum Error {
5+
#[error("collection not found")]
106
CollectionNotFound,
11-
ObjectNotFound,
12-
Serialization(serde_json::Error),
13-
Unexpected(Box<dyn std::error::Error>),
14-
}
15-
16-
impl Error {
17-
pub fn kind(&self) -> &ErrorKind {
18-
&self.0
19-
}
20-
}
217

22-
impl fmt::Display for Error {
23-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24-
match self.kind() {
25-
ErrorKind::CollectionNotFound => write!(f, "colelction could not be found"),
26-
ErrorKind::ObjectNotFound => write!(f, "object could not be found"),
27-
ErrorKind::Serialization(err) => write!(f, "object serialization failed: {err}"),
28-
ErrorKind::Unexpected(err) => err.fmt(f),
29-
}
30-
}
31-
}
32-
33-
impl std::error::Error for Error {}
34-
35-
impl From<ErrorKind> for Error {
36-
fn from(value: ErrorKind) -> Self {
37-
Error(Box::new(value))
38-
}
39-
}
8+
#[error("object not found")]
9+
ObjectNotFound,
4010

41-
impl From<serde_json::Error> for Error {
42-
fn from(value: serde_json::Error) -> Self {
43-
ErrorKind::Serialization(value).into()
44-
}
45-
}
11+
#[error("serialization error: {0}")]
12+
Serialization(#[from] serde_json::Error),
4613

47-
impl From<anyhow::Error> for Error {
48-
fn from(value: anyhow::Error) -> Self {
49-
ErrorKind::Unexpected(value.into()).into()
50-
}
14+
#[error(transparent)]
15+
Unexpected(#[from] anyhow::Error),
5116
}

lib/controller/objects.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use super::errors::ErrorKind;
1+
use super::errors::Error;
22
use super::errors::Result;
33
use super::util::build_key;
44
use super::util::GROUP_COLLECTIONS;
55
use super::util::GROUP_OBJECTS;
66
use super::Controller;
7+
use crate::models::Update;
78
use crate::models::{Object, ObjectRequest};
89
use chrono::Local;
910

@@ -35,19 +36,15 @@ impl Controller {
3536
&self,
3637
collection: &str,
3738
id: &str,
38-
object: ObjectRequest,
39+
new_object: <Object as Update>::With,
3940
) -> Result<Object> {
40-
let Some(current) = self.get_object(collection, id).await? else {
41-
return Err(ErrorKind::ObjectNotFound.into());
41+
let Some(mut object) = self.get_object(collection, id).await? else {
42+
return Err(Error::ObjectNotFound);
4243
};
4344

44-
let new = Object {
45-
name: object.name,
46-
data: object.data,
47-
..current
48-
};
45+
object.update(new_object);
4946

50-
let serialized = serde_json::to_vec(&new)?;
47+
let serialized = serde_json::to_vec(&object)?;
5148

5249
self.persistence
5350
.set(
@@ -57,7 +54,7 @@ impl Controller {
5754
)
5855
.await?;
5956

60-
Ok(new)
57+
Ok(object)
6158
}
6259

6360
pub async fn get_object(&self, collection: &str, id: &str) -> Result<Option<Object>> {
@@ -108,7 +105,7 @@ impl Controller {
108105
if collection_exists {
109106
Ok(())
110107
} else {
111-
Err(ErrorKind::CollectionNotFound.into())
108+
Err(Error::CollectionNotFound)
112109
}
113110
}
114111
}

lib/models/data.rs

+23
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,26 @@ pub enum Entry {
4040
Vec(Vec<Entry>),
4141
Bool(bool),
4242
}
43+
44+
pub trait Update {
45+
type With;
46+
47+
fn update(&mut self, with: Self::With);
48+
}
49+
50+
impl Update for Collection {
51+
type With = CollectionRequest;
52+
53+
fn update(&mut self, with: Self::With) {
54+
self.name = with.name;
55+
}
56+
}
57+
58+
impl Update for Object {
59+
type With = ObjectRequest;
60+
61+
fn update(&mut self, with: Self::With) {
62+
self.name = with.name;
63+
self.data = with.data;
64+
}
65+
}

lib/utils/macros.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@ macro_rules! expect {
2323
}
2424
};
2525

26-
($expression:expr, $pattern:pat_param => $bail:expr) => {
26+
($expression:expr, $pattern:pat_param => $bail:expr $(,$extra_pattern:pat_param => $extra_bail:expr)*) => {
2727
match $expression {
2828
Ok(v) => v,
2929
$pattern => {
3030
return $bail;
3131
}
32+
$(
33+
$extra_pattern => {
34+
return $extra_bail;
35+
}
36+
)*
3237
}
3338
};
3439
}

0 commit comments

Comments
 (0)