perfectly working system
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
-- Add migration script here
|
||||||
|
CREATE TABLE processed_data (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
|
// proto/api.proto
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package my_service;
|
package multieko2;
|
||||||
|
|
||||||
service MyService {
|
service DataProcessor {
|
||||||
rpc MyMethod (MyRequest) returns (MyResponse);
|
rpc ProcessData (DataRequest) returns (DataResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message MyRequest {
|
message DataRequest {
|
||||||
int32 id = 1;
|
string data = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MyResponse {
|
message DataResponse {
|
||||||
string message = 1;
|
string processed_data = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
use crate::proto::api::accounting_client::AccountingClient;
|
// src/client/mod.rs
|
||||||
|
use tonic::transport::Channel;
|
||||||
|
use crate::proto::multieko2::data_processor_client::DataProcessorClient;
|
||||||
|
use crate::proto::multieko2::DataRequest;
|
||||||
|
|
||||||
pub async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
|
pub async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut client = AccountingClient::connect("http://[::1]:50051").await?;
|
let mut client = DataProcessorClient::connect("http://[::1]:50051").await?;
|
||||||
// Client implementation
|
|
||||||
|
let request = tonic::Request::new(DataRequest {
|
||||||
|
data: "hello world".to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let response = client.process_data(request).await?;
|
||||||
|
|
||||||
|
println!("RESPONSE={:?}", response.into_inner().processed_data);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
// src/lib.rs
|
// src/lib.rs
|
||||||
pub mod db;
|
pub mod db;
|
||||||
|
pub mod client;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
pub mod proto;
|
||||||
|
|||||||
28
src/main.rs
28
src/main.rs
@@ -1,33 +1,21 @@
|
|||||||
// src/main.rs
|
// src/main.rs
|
||||||
use tonic::transport::Server;
|
use std::env;
|
||||||
use sqlx::PgPool;
|
use dotenvy::dotenv;
|
||||||
use crate::db;
|
use multieko2::{server, client, db};
|
||||||
use crate::server;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Load .env file
|
dotenv().ok();
|
||||||
dotenvy::dotenv().ok();
|
|
||||||
|
|
||||||
// Initialize database
|
// Initialize database
|
||||||
let db_config = db::DatabaseConfig::from_env();
|
let db_config = db::DatabaseConfig::from_env();
|
||||||
let db_pool = db::create_pool(&db_config)
|
let db_pool = db::create_pool(&db_config).await?;
|
||||||
.await
|
|
||||||
.expect("Failed to create database pool");
|
|
||||||
|
|
||||||
|
match env::args().nth(1).as_deref() {
|
||||||
// Check database connection
|
|
||||||
db::check_connection(&db_pool)
|
|
||||||
.await
|
|
||||||
.expect("Failed to connect to database");
|
|
||||||
|
|
||||||
// Choose mode based on command line arguments
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
match args.get(1).map(|s| s.as_str()) {
|
|
||||||
Some("server") => server::run_server(db_pool).await?,
|
Some("server") => server::run_server(db_pool).await?,
|
||||||
Some("client") => client::run_client().await?,
|
Some("client") => client::run_client().await?,
|
||||||
Some("standalone") => standalone::run().await?,
|
_ => println!("Usage: cargo run -- [server|client]"),
|
||||||
_ => println!("Usage: [server|client|standalone]"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/proto/mod.rs
Normal file
3
src/proto/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod multieko2 {
|
||||||
|
tonic::include_proto!("multieko2");
|
||||||
|
}
|
||||||
@@ -1,27 +1,51 @@
|
|||||||
|
// src/server/mod.rs
|
||||||
use tonic::{Request, Response, Status};
|
use tonic::{Request, Response, Status};
|
||||||
use crate::{db, proto::api::*};
|
use crate::db;
|
||||||
|
use crate::proto::multieko2::{
|
||||||
|
data_processor_server::{DataProcessor, DataProcessorServer},
|
||||||
|
DataRequest, DataResponse
|
||||||
|
};
|
||||||
|
|
||||||
pub struct AccountingService {
|
pub struct DataProcessorService {
|
||||||
db_pool: sqlx::PgPool,
|
db_pool: sqlx::PgPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl accounting_server::Accounting for AccountingService {
|
impl DataProcessor for DataProcessorService {
|
||||||
async fn create_account(
|
async fn process_data(
|
||||||
&self,
|
&self,
|
||||||
request: Request<CreateAccountRequest>,
|
request: Request<DataRequest>,
|
||||||
) -> Result<Response<CreateAccountResponse>, Status> {
|
) -> Result<Response<DataResponse>, Status> {
|
||||||
// Database implementation
|
let data = request.into_inner().data;
|
||||||
|
|
||||||
|
// Store data in database
|
||||||
|
let stored_data = sqlx::query!(
|
||||||
|
"INSERT INTO processed_data (content) VALUES ($1) RETURNING id",
|
||||||
|
data
|
||||||
|
)
|
||||||
|
.fetch_one(&self.db_pool)
|
||||||
|
.await
|
||||||
|
.map_err(|e| Status::internal(e.to_string()))?;
|
||||||
|
|
||||||
|
// Simple processing: convert to uppercase
|
||||||
|
let processed_data = data.to_uppercase();
|
||||||
|
|
||||||
|
Ok(Response::new(DataResponse {
|
||||||
|
processed_data: format!("Processed data with ID: {}", stored_data.id)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_server(pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
|
pub async fn run_server(db_pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let addr = "[::1]:50051".parse()?;
|
let addr = "[::1]:50051".parse()?;
|
||||||
|
let service = DataProcessorService { db_pool };
|
||||||
|
|
||||||
|
println!("Server listening on {}", addr);
|
||||||
|
|
||||||
tonic::transport::Server::builder()
|
tonic::transport::Server::builder()
|
||||||
.add_service(accounting_server::AccountingServer::new(
|
.add_service(DataProcessorServer::new(service))
|
||||||
AccountingService { db_pool: pool }
|
|
||||||
))
|
|
||||||
.serve(addr)
|
.serve(addr)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
use crate::server::run_server;
|
|
||||||
use crate::client::run_client;
|
|
||||||
use sqlx::PgPool;
|
|
||||||
|
|
||||||
pub async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
// Set up local PostgreSQL connection
|
|
||||||
let db_pool = PgPool::connect("postgres://user:password@localhost/multieko2").await?;
|
|
||||||
|
|
||||||
// Run the server in the background
|
|
||||||
let server_handle = tokio::spawn(async move {
|
|
||||||
run_server(db_pool).await.unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Run the client
|
|
||||||
run_client("http://[::1]:50051".to_string()).await?;
|
|
||||||
|
|
||||||
// Wait for the server to finish (it won't, but this keeps the app running)
|
|
||||||
server_handle.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user