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

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/target /target
.env

232
Cargo.lock generated
View File

@@ -246,6 +246,15 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
[[package]]
name = "cc"
version = "1.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9"
dependencies = [
"shlex",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@@ -313,6 +322,22 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.17" version = "0.2.17"
@@ -484,6 +509,21 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.1" version = "1.2.1"
@@ -1079,11 +1119,14 @@ name = "multieko2"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"dotenvy",
"prost", "prost",
"sqlx", "sqlx",
"tokio", "tokio",
"tonic", "tonic",
"tonic-build", "tonic-build",
"tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@@ -1092,6 +1135,33 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03"
[[package]]
name = "native-tls"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num-bigint-dig" name = "num-bigint-dig"
version = "0.8.4" version = "0.8.4"
@@ -1154,6 +1224,56 @@ version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "openssl"
version = "0.10.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-probe"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
version = "0.9.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "parking" name = "parking"
version = "2.2.1" version = "2.2.1"
@@ -1475,12 +1595,44 @@ version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "schannel"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
dependencies = [
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.217" version = "1.0.217"
@@ -1547,6 +1699,21 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.2" version = "1.4.2"
@@ -1646,6 +1813,7 @@ dependencies = [
"indexmap 2.7.1", "indexmap 2.7.1",
"log", "log",
"memchr", "memchr",
"native-tls",
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"serde", "serde",
@@ -1891,6 +2059,16 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]] [[package]]
name = "tinystr" name = "tinystr"
version = "0.7.6" version = "0.7.6"
@@ -2089,6 +2267,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@@ -2159,6 +2363,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
@@ -2211,6 +2421,28 @@ dependencies = [
"wasite", "wasite",
] ]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

View File

@@ -5,8 +5,14 @@ edition = "2021"
[dependencies] [dependencies]
clap = { version = "4.5.29", features = ["derive"] } clap = { version = "4.5.29", features = ["derive"] }
dotenvy = "0.15.7"
prost = "0.13.5" prost = "0.13.5"
sqlx = { version = "0.8.3", features = ["postgres", "runtime-tokio"] } sqlx = { version = "0.8.3", features = ["postgres", "runtime-tokio", "runtime-tokio-native-tls"] }
tokio = { version = "1.43.0", features = ["full", "macros"] } tokio = { version = "1.43.0", features = ["full", "macros"] }
tonic = "0.12.3" tonic = "0.12.3"
tonic-build = "0.12.3" tonic-build = "0.12.3"
tracing = "0.1.41"
tracing-subscriber = "0.3.19"
[build-dependencies]
tonic-build = "0.12"

4
build.rs Normal file
View File

@@ -0,0 +1,4 @@
// build.rs
fn main() {
tonic_build::compile_protos("proto/api.proto").unwrap();
}

View File

@@ -0,0 +1,15 @@
syntax = "proto3";
package my_service;
service MyService {
rpc MyMethod (MyRequest) returns (MyResponse);
}
message MyRequest {
int32 id = 1;
}
message MyResponse {
string message = 1;
}

View File

@@ -1,21 +1,7 @@
use multieko2::accounting_client::AccountingClient; use crate::proto::api::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);
pub async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
let mut client = AccountingClient::connect("http://[::1]:50051").await?;
// Client implementation
Ok(()) 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; use sqlx::PgPool;
use crate::db;
#[derive(Parser)] use crate::server;
struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Standalone,
Server,
Client { server_url: String },
}
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Cli::parse(); // Load .env file
dotenvy::dotenv().ok();
match args.command { // Initialize database
Commands::Standalone => { let db_config = db::DatabaseConfig::from_env();
standalone::run().await?; let db_pool = db::create_pool(&db_config)
} .await
Commands::Server => { .expect("Failed to create database pool");
let db_pool = PgPool::connect("postgres://user:password@localhost/multieko2").await?;
server::run_server(db_pool).await?;
} // Check database connection
Commands::Client { server_url } => { db::check_connection(&db_pool)
client::run_client(server_url).await?; .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(()) Ok(())
} }

View File

@@ -1,52 +1,27 @@
use tonic::{Request, Response, Status}; use tonic::{Request, Response, Status};
use sqlx::PgPool; use crate::{db, proto::api::*};
use multieko2::accounting_server::{Accounting, AccountingServer};
use multieko2::{CreateAccountRequest, CreateAccountResponse, GetAccountRequest, GetAccountResponse};
pub struct MyAccountingService { pub struct AccountingService {
db_pool: PgPool, db_pool: sqlx::PgPool,
} }
#[tonic::async_trait] #[tonic::async_trait]
impl Accounting for MyAccountingService { impl accounting_server::Accounting for AccountingService {
async fn create_account( async fn create_account(
&self, &self,
request: Request<CreateAccountRequest>, request: Request<CreateAccountRequest>,
) -> Result<Response<CreateAccountResponse>, Status> { ) -> Result<Response<CreateAccountResponse>, Status> {
let name = request.into_inner().name; // Database implementation
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,
}))
} }
} }
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 addr = "[::1]:50051".parse()?;
let service = MyAccountingService { db_pool };
tonic::transport::Server::builder() tonic::transport::Server::builder()
.add_service(AccountingServer::new(service)) .add_service(accounting_server::AccountingServer::new(
AccountingService { db_pool: pool }
))
.serve(addr) .serve(addr)
.await?; .await?;
Ok(()) Ok(())
} }