* Move core implementations to a standalone crate * Set up integration test skeleton in `core` * Demonstrate mock testing with query * Move Rocket api code to a standalone crate * Add mock execution * Add MyDataMyConsent in COMMUNITY.md (#889) * Add MyDataMyConsent in COMMUNITY.md * Update MyDataMyConsent description in COMMUNITY.md * Update COMMUNITY.md Chronological order * [cli] bump sea-schema to 0.9.3 (SeaQL/sea-orm#876) * Update CHNAGELOG PR links * 0.9.1 CHANGELOG * Auto discover and run all issues & examples CI (#903) * Auto discover and run all [issues] CI * Auto discover and run all examples CI * Fixup * Testing * Test [issues] * Compile prepare_mock_db() conditionally based on "mock" feature * Update workflow job to run mock test if `core` folder exists * Update Actix3 example * Fix merge conflict human error * Update usize used in paginate to u64 (PR#789) * Update sea-orm version in the Rocket example to 0.10.0 * Fix GitHub workflow to run mock test for core crates * Increase the robustness of core crate check by verifying that the `core` folder is a crate * Update Actix(4) example * Update Axum example * Update GraphQL example * Update Jsonrpsee example * Update Poem example * Update Tonic example * Cargo fmt * Update Salvo example * Update path of core/Cargo.toml in README.md * Add mock test instruction in README.md * Refactoring * Fix Rocket examples Co-authored-by: Amit Goyani <63532626+itsAmitGoyani@users.noreply.github.com> Co-authored-by: Billy Chan <ccw.billy.123@gmail.com>
144 lines
3.8 KiB
Rust
144 lines
3.8 KiB
Rust
use tonic::transport::Server;
|
|
use tonic::{Request, Response, Status};
|
|
|
|
use entity::post;
|
|
use migration::{Migrator, MigratorTrait};
|
|
use tonic_example_core::{
|
|
sea_orm::{Database, DatabaseConnection},
|
|
Mutation, Query,
|
|
};
|
|
|
|
use std::env;
|
|
|
|
pub mod post_mod {
|
|
tonic::include_proto!("post");
|
|
}
|
|
|
|
use post_mod::{
|
|
blogpost_server::{Blogpost, BlogpostServer},
|
|
Post, PostId, PostList, PostPerPage, ProcessStatus,
|
|
};
|
|
|
|
impl Post {
|
|
fn into_model(self) -> post::Model {
|
|
post::Model {
|
|
id: self.id,
|
|
title: self.title,
|
|
text: self.content,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct MyServer {
|
|
connection: DatabaseConnection,
|
|
}
|
|
|
|
#[tonic::async_trait]
|
|
impl Blogpost for MyServer {
|
|
async fn get_posts(&self, request: Request<PostPerPage>) -> Result<Response<PostList>, Status> {
|
|
let conn = &self.connection;
|
|
let posts_per_page = request.into_inner().per_page;
|
|
|
|
let mut response = PostList { post: Vec::new() };
|
|
|
|
let (posts, _) = Query::find_posts_in_page(conn, 1, posts_per_page)
|
|
.await
|
|
.expect("Cannot find posts in page");
|
|
|
|
for post in posts {
|
|
response.post.push(Post {
|
|
id: post.id,
|
|
title: post.title,
|
|
content: post.text,
|
|
});
|
|
}
|
|
|
|
Ok(Response::new(response))
|
|
}
|
|
|
|
async fn add_post(&self, request: Request<Post>) -> Result<Response<PostId>, Status> {
|
|
let conn = &self.connection;
|
|
|
|
let input = request.into_inner().into_model();
|
|
|
|
let inserted = Mutation::create_post(conn, input)
|
|
.await
|
|
.expect("could not insert post");
|
|
|
|
let response = PostId {
|
|
id: inserted.id.unwrap(),
|
|
};
|
|
|
|
Ok(Response::new(response))
|
|
}
|
|
|
|
async fn update_post(&self, request: Request<Post>) -> Result<Response<ProcessStatus>, Status> {
|
|
let conn = &self.connection;
|
|
let input = request.into_inner().into_model();
|
|
|
|
match Mutation::update_post_by_id(conn, input.id, input).await {
|
|
Ok(_) => Ok(Response::new(ProcessStatus { success: true })),
|
|
Err(_) => Ok(Response::new(ProcessStatus { success: false })),
|
|
}
|
|
}
|
|
|
|
async fn delete_post(
|
|
&self,
|
|
request: Request<PostId>,
|
|
) -> Result<Response<ProcessStatus>, Status> {
|
|
let conn = &self.connection;
|
|
let id = request.into_inner().id;
|
|
|
|
match Mutation::delete_post(conn, id).await {
|
|
Ok(_) => Ok(Response::new(ProcessStatus { success: true })),
|
|
Err(_) => Ok(Response::new(ProcessStatus { success: false })),
|
|
}
|
|
}
|
|
|
|
async fn get_post_by_id(&self, request: Request<PostId>) -> Result<Response<Post>, Status> {
|
|
let conn = &self.connection;
|
|
let id = request.into_inner().id;
|
|
|
|
if let Some(post) = Query::find_post_by_id(conn, id).await.ok().flatten() {
|
|
Ok(Response::new(Post {
|
|
id,
|
|
title: post.title,
|
|
content: post.text,
|
|
}))
|
|
} else {
|
|
Err(Status::new(
|
|
tonic::Code::Aborted,
|
|
"Could not find post with id ".to_owned() + &id.to_string(),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn start() -> Result<(), Box<dyn std::error::Error>> {
|
|
let addr = "0.0.0.0:50051".parse()?;
|
|
|
|
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
|
|
|
// establish database connection
|
|
let connection = Database::connect(&database_url).await?;
|
|
Migrator::up(&connection, None).await?;
|
|
|
|
let hello_server = MyServer { connection };
|
|
Server::builder()
|
|
.add_service(BlogpostServer::new(hello_server))
|
|
.serve(addr)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn main() {
|
|
let result = start();
|
|
|
|
if let Some(err) = result.err() {
|
|
println!("Error: {}", err);
|
|
}
|
|
}
|