not working, basic structure with grpc

This commit is contained in:
filipriec
2025-02-15 22:57:40 +01:00
parent 9233c769b0
commit b871d40759
10 changed files with 352 additions and 80 deletions

View File

@@ -1,21 +1,7 @@
use multieko2::accounting_client::AccountingClient;
use multieko2::{CreateAccountRequest, GetAccountRequest};
pub async fn run_client(server_url: String) -> Result<(), Box<dyn std::error::Error>> {
let mut client = AccountingClient::connect(server_url).await?;
// Create an account
let create_response = client
.create_account(CreateAccountRequest { name: "John Doe".into() })
.await?;
println!("Created account with ID: {}", create_response.into_inner().id);
// Get an account
let get_response = client
.get_account(GetAccountRequest { id: "1".into() })
.await?;
let account = get_response.into_inner();
println!("Account ID: {}, Name: {}", account.id, account.name);
use crate::proto::api::accounting_client::AccountingClient;
pub async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
let mut client = AccountingClient::connect("http://[::1]:50051").await?;
// Client implementation
Ok(())
}

52
src/db.rs Normal file
View File

@@ -0,0 +1,52 @@
// src/db.rs
use sqlx::postgres::{PgPool, PgPoolOptions};
use std::time::Duration;
use tracing::info;
#[derive(Debug)]
pub struct DatabaseConfig {
pub username: String,
pub password: String,
pub host: String,
pub port: u16,
pub database_name: String,
pub max_connections: u32,
}
impl DatabaseConfig {
pub fn from_env() -> Self {
Self {
username: std::env::var("RUST_DB_USER").expect("RUST_DB_USER must be set"),
password: std::env::var("RUST_DB_PASSWORD").expect("RUST_DB_PASSWORD must be set"),
host: std::env::var("RUST_DB_HOST").expect("RUST_DB_HOST must be set"),
port: std::env::var("RUST_DB_PORT")
.expect("RUST_DB_PORT must be set")
.parse()
.expect("RUST_DB_PORT must be a valid port number"),
database_name: std::env::var("RUST_DB_NAME").expect("RUST_DB_NAME must be set"),
max_connections: 5,
}
}
pub fn connection_string(&self) -> String {
format!(
"postgres://{}:{}@{}:{}/{}",
self.username, self.password, self.host, self.port, self.database_name
)
}
}
pub async fn create_pool(config: &DatabaseConfig) -> Result<PgPool, sqlx::Error> {
let conn_str = config.connection_string();
info!("Connecting to database: {}", conn_str);
PgPoolOptions::new()
.max_connections(config.max_connections)
.acquire_timeout(Duration::from_secs(3))
.connect(&conn_str)
.await
}
pub async fn check_connection(pool: &PgPool) -> Result<(), sqlx::Error> {
sqlx::query("SELECT 1").execute(pool).await?;
Ok(())
}

View File

@@ -0,0 +1,3 @@
// src/lib.rs
pub mod db;
pub mod server;

View File

@@ -1,35 +1,33 @@
use clap::{Parser, Subcommand};
// src/main.rs
use tonic::transport::Server;
use sqlx::PgPool;
#[derive(Parser)]
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Standalone,
Server,
Client { server_url: String },
}
use crate::db;
use crate::server;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse();
// Load .env file
dotenvy::dotenv().ok();
match args.command {
Commands::Standalone => {
standalone::run().await?;
}
Commands::Server => {
let db_pool = PgPool::connect("postgres://user:password@localhost/multieko2").await?;
server::run_server(db_pool).await?;
}
Commands::Client { server_url } => {
client::run_client(server_url).await?;
}
// Initialize database
let db_config = db::DatabaseConfig::from_env();
let db_pool = db::create_pool(&db_config)
.await
.expect("Failed to create database pool");
// 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("client") => client::run_client().await?,
Some("standalone") => standalone::run().await?,
_ => println!("Usage: [server|client|standalone]"),
}
Ok(())
}

View File

@@ -1,52 +1,27 @@
use tonic::{Request, Response, Status};
use sqlx::PgPool;
use multieko2::accounting_server::{Accounting, AccountingServer};
use multieko2::{CreateAccountRequest, CreateAccountResponse, GetAccountRequest, GetAccountResponse};
use crate::{db, proto::api::*};
pub struct MyAccountingService {
db_pool: PgPool,
pub struct AccountingService {
db_pool: sqlx::PgPool,
}
#[tonic::async_trait]
impl Accounting for MyAccountingService {
impl accounting_server::Accounting for AccountingService {
async fn create_account(
&self,
request: Request<CreateAccountRequest>,
) -> Result<Response<CreateAccountResponse>, Status> {
let name = request.into_inner().name;
let account = sqlx::query!("INSERT INTO accounts (name) VALUES ($1) RETURNING id", name)
.fetch_one(&self.db_pool)
.await
.map_err(|e| Status::internal(e.to_string()))?;
Ok(Response::new(CreateAccountResponse { id: account.id.to_string() }))
}
async fn get_account(
&self,
request: Request<GetAccountRequest>,
) -> Result<Response<GetAccountResponse>, Status> {
let id = request.into_inner().id;
let account = sqlx::query!("SELECT id, name FROM accounts WHERE id = $1", id)
.fetch_one(&self.db_pool)
.await
.map_err(|e| Status::internal(e.to_string()))?;
Ok(Response::new(GetAccountResponse {
id: account.id.to_string(),
name: account.name,
}))
// Database implementation
}
}
pub async fn run_server(db_pool: PgPool) -> Result<(), Box<dyn std::error::Error>> {
pub async fn run_server(pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let service = MyAccountingService { db_pool };
tonic::transport::Server::builder()
.add_service(AccountingServer::new(service))
.add_service(accounting_server::AccountingServer::new(
AccountingService { db_pool: pool }
))
.serve(addr)
.await?;
Ok(())
}