Move to sqlx
Some checks failed
Build docker image / Build-Docker-Image (push) Has been cancelled

This commit is contained in:
2024-12-24 21:10:59 +01:00
parent b4f43183b1
commit 6ff96eb7d7
19 changed files with 1623 additions and 7169 deletions

View File

@@ -1,2 +0,0 @@
[alias]
prisma = "run -p prisma-cli --"

View File

@@ -0,0 +1,58 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT * FROM services WHERE id = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "0137a8e4f27051dfccfb79da48211f5bb0fd54079f082b337b0eff84add7432d"
}

View File

@@ -0,0 +1,62 @@
{
"db_name": "PostgreSQL",
"query": "\n INSERT INTO services (token, \"user\", status, cache, username) VALUES ($1, $2, $3, $4, $5) RETURNING *\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Int8",
"Varchar",
"Varchar",
"Varchar"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "0b3d1cf81684128484ac99bcc2259773a5e8fc6f2499f3fa7c085fc4d21e0d91"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT COUNT(*) FROM services WHERE \"user\" = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Int8"
]
},
"nullable": [
null
]
},
"hash": "84f0d257d3e3a033848820a88875e9f19e6e41ec0b4a518dbe8150410b0e6191"
}

View File

@@ -0,0 +1,56 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT * FROM services\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "9978e9199895c9fc8fe8f7fcfc30ff8d2a2d586e116a5b94f8e40e7c2971a110"
}

View File

@@ -0,0 +1,58 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE FROM services WHERE id = $1 RETURNING *\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Int4"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "bece50bc2ce198404dbdea3c980e5a1d3940f74007ecf6ebfd48b7a240001747"
}

View File

@@ -0,0 +1,59 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE services SET cache = $1 WHERE id = $2 RETURNING *\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Int4"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "df547cbddb771167af7188799cbdfc473065768ec9e1b7791b2a2cb03ddc07b9"
}

View File

@@ -0,0 +1,59 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE services SET status = $1 WHERE id = $2 RETURNING *\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "token",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "user",
"type_info": "Int8"
},
{
"ordinal": 3,
"name": "status",
"type_info": "Varchar"
},
{
"ordinal": 4,
"name": "created_time",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "cache",
"type_info": "Varchar"
},
{
"ordinal": 6,
"name": "username",
"type_info": "Varchar"
}
],
"parameters": {
"Left": [
"Varchar",
"Int4"
]
},
"nullable": [
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "ed40414712a25612c336364c52181f98531a801fbe8bdd885683f56c291e3337"
}

3409
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,26 +3,21 @@ name = "services_manager_server"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[workspace]
members = [
"prisma-cli"
]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
once_cell = "1.20.1" once_cell = "1.20.2"
prisma-client-rust = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.10", default-features = false, features = ["postgresql"] } serde = { version = "1.0.216", features = ["derive"] }
serde = { version = "1.0.210", features = ["derive"] }
tokio = { version = "1.40.0", features = ["full"] } tokio = { version = "1.42.0", features = ["full"] }
axum = { version = "0.7.7", features = ["json"] } axum = { version = "0.7.9", features = ["json"] }
axum-prometheus = "0.7.0" axum-prometheus = "0.7.0"
chrono = "0.4.38" chrono = { version = "0.4.39", features = ["serde"] }
sentry = { version = "0.34.0", features = ["debug-images"] } sentry = { version = "0.35.0", features = ["debug-images"] }
tracing = "0.1.40" tracing = "0.1.41"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"]} tracing-subscriber = { version = "0.3.19", features = ["env-filter"]}
sentry-tracing = "0.34.0" sentry-tracing = "0.35.0"
tower-http = { version = "0.6.1", features = ["trace"] } tower-http = { version = "0.6.2", features = ["trace"] }
sqlx = { version = "0.8.2", features = ["runtime-tokio", "postgres", "macros", "chrono"] }

View File

@@ -1,3 +0,0 @@
node_modules
# Keep environment variables out of version control
.env

3195
prisma-cli/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
[package]
name = "prisma-cli"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
prisma-client-rust-cli = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.10", default-features = false, features = ["postgresql"] }

View File

@@ -1,3 +0,0 @@
fn main() {
prisma_client_rust_cli::run();
}

View File

@@ -1,21 +0,0 @@
generator client {
provider = "cargo prisma"
output = "../src/prisma.rs"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Service {
id Int @id @default(autoincrement())
token String @unique @db.VarChar(128)
user BigInt
status String @db.VarChar(12)
created_time DateTime @db.Timestamptz(6)
cache String @db.VarChar(12)
username String @db.VarChar(64)
@@map("services")
}

View File

@@ -1,8 +1,10 @@
use crate::{config::CONFIG, prisma::PrismaClient}; use crate::config::CONFIG;
pub async fn get_prisma_client() -> PrismaClient { use sqlx::{postgres::PgPoolOptions, PgPool};
pub async fn get_pg_pool() -> PgPool {
let database_url: String = format!( let database_url: String = format!(
"postgresql://{}:{}@{}:{}/{}?connection_limit=1", "postgresql://{}:{}@{}:{}/{}",
CONFIG.postgres_user, CONFIG.postgres_user,
CONFIG.postgres_password, CONFIG.postgres_password,
CONFIG.postgres_host, CONFIG.postgres_host,
@@ -10,9 +12,9 @@ pub async fn get_prisma_client() -> PrismaClient {
CONFIG.postgres_db CONFIG.postgres_db
); );
PrismaClient::_builder() PgPoolOptions::new()
.with_url(database_url) .max_connections(1)
.build() .connect(&database_url)
.await .await
.unwrap() .unwrap()
} }

View File

@@ -1,6 +1,5 @@
pub mod config; pub mod config;
pub mod db; pub mod db;
pub mod prisma;
pub mod views; pub mod views;
use sentry::{integrations::debug_images::DebugImagesIntegration, types::Dsn, ClientOptions}; use sentry::{integrations::debug_images::DebugImagesIntegration, types::Dsn, ClientOptions};

File diff suppressed because one or more lines are too long

View File

@@ -7,27 +7,37 @@ use axum::{
Extension, Json, Router, Extension, Json, Router,
}; };
use axum_prometheus::PrometheusMetricLayer; use axum_prometheus::PrometheusMetricLayer;
use serde::Deserialize; use chrono::DateTime;
use std::sync::Arc; use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use tower_http::trace::{self, TraceLayer}; use tower_http::trace::{self, TraceLayer};
use tracing::Level; use tracing::Level;
use crate::{ use crate::{config::CONFIG, db::get_pg_pool};
config::CONFIG,
db::get_prisma_client,
prisma::{service, PrismaClient},
};
pub type Database = Extension<Arc<PrismaClient>>; pub type Database = Extension<PgPool>;
const BOTS_COUNT_LIMIT: i64 = 5; const BOTS_COUNT_LIMIT: i64 = 5;
#[derive(sqlx::FromRow, Serialize)]
pub struct Service {
pub id: i32,
pub token: String,
pub user: i64,
pub status: String,
pub created_time: DateTime<chrono::Local>,
pub cache: String,
pub username: String,
}
async fn get_services(db: Database) -> impl IntoResponse { async fn get_services(db: Database) -> impl IntoResponse {
let services = db let services = sqlx::query_as!(
.service() Service,
.find_many(vec![]) r#"
.order_by(service::id::order(prisma_client_rust::Direction::Asc)) SELECT * FROM services
.exec() "#
)
.fetch_all(&db.0)
.await .await
.unwrap(); .unwrap();
@@ -35,10 +45,14 @@ async fn get_services(db: Database) -> impl IntoResponse {
} }
async fn get_service(Path(id): Path<i32>, db: Database) -> impl IntoResponse { async fn get_service(Path(id): Path<i32>, db: Database) -> impl IntoResponse {
let service = db let service = sqlx::query_as!(
.service() Service,
.find_unique(service::id::equals(id)) r#"
.exec() SELECT * FROM services WHERE id = $1
"#,
id
)
.fetch_optional(&db.0)
.await .await
.unwrap(); .unwrap();
@@ -49,19 +63,19 @@ async fn get_service(Path(id): Path<i32>, db: Database) -> impl IntoResponse {
} }
async fn delete_service(Path(id): Path<i32>, db: Database) -> impl IntoResponse { async fn delete_service(Path(id): Path<i32>, db: Database) -> impl IntoResponse {
let service = db let service = sqlx::query_as!(
.service() Service,
.find_unique(service::id::equals(id)) r#"
.exec() DELETE FROM services WHERE id = $1 RETURNING *
"#,
id
)
.fetch_optional(&db.0)
.await .await
.unwrap(); .unwrap();
match service { match service {
Some(v) => { Some(v) => Json(v).into_response(),
let _ = db.service().delete(service::id::equals(id)).exec().await;
Json(v).into_response()
}
None => StatusCode::NOT_FOUND.into_response(), None => StatusCode::NOT_FOUND.into_response(),
} }
} }
@@ -84,29 +98,33 @@ async fn create_service(db: Database, Json(data): Json<CreateServiceData>) -> im
username, username,
} = data; } = data;
let exist_count = db let exist_count = sqlx::query_scalar!(
.service() r#"
.count(vec![service::user::equals(user)]) SELECT COUNT(*) FROM services WHERE "user" = $1
.exec() "#,
user
)
.fetch_one(&db.0)
.await .await
.unwrap_or(Some(0))
.unwrap(); .unwrap();
if exist_count >= BOTS_COUNT_LIMIT { if exist_count >= BOTS_COUNT_LIMIT {
return StatusCode::PAYMENT_REQUIRED.into_response(); return StatusCode::PAYMENT_REQUIRED.into_response();
}; };
let service = db let service = sqlx::query_as!(
.service() Service,
.create( r#"
INSERT INTO services (token, "user", status, cache, username) VALUES ($1, $2, $3, $4, $5) RETURNING *
"#,
token, token,
user, user,
status, status,
chrono::offset::Local::now().into(),
cache, cache,
username, username
vec![],
) )
.exec() .fetch_one(&db.0)
.await .await
.unwrap(); .unwrap();
@@ -118,15 +136,21 @@ async fn update_state(
db: Database, db: Database,
Json(state): Json<String>, Json(state): Json<String>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let service = db let service = sqlx::query_as!(
.service() Service,
.update(service::id::equals(id), vec![service::status::set(state)]) r#"
.exec() UPDATE services SET status = $1 WHERE id = $2 RETURNING *
.await; "#,
state,
id
)
.fetch_optional(&db.0)
.await
.unwrap();
match service { match service {
Ok(v) => Json(v).into_response(), Some(v) => Json(v).into_response(),
Err(_) => StatusCode::NOT_FOUND.into_response(), None => StatusCode::NOT_FOUND.into_response(),
} }
} }
@@ -135,15 +159,21 @@ async fn update_cache(
db: Database, db: Database,
Json(cache): Json<String>, Json(cache): Json<String>,
) -> impl IntoResponse { ) -> impl IntoResponse {
let service = db let service = sqlx::query_as!(
.service() Service,
.update(service::id::equals(id), vec![service::cache::set(cache)]) r#"
.exec() UPDATE services SET cache = $1 WHERE id = $2 RETURNING *
.await; "#,
cache,
id
)
.fetch_optional(&db.0)
.await
.unwrap();
match service { match service {
Ok(v) => Json(v).into_response(), Some(v) => Json(v).into_response(),
Err(_) => StatusCode::NOT_FOUND.into_response(), None => StatusCode::NOT_FOUND.into_response(),
} }
} }
@@ -169,7 +199,7 @@ async fn auth(req: Request<axum::body::Body>, next: Next) -> Result<Response, St
} }
pub async fn get_router() -> Router { pub async fn get_router() -> Router {
let client = Arc::new(get_prisma_client().await); let client = get_pg_pool().await;
let (prometheus_layer, metric_handle) = PrometheusMetricLayer::pair(); let (prometheus_layer, metric_handle) = PrometheusMetricLayer::pair();