various: reuse HTTP client; eliminate intermediate string allocations; add tests

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I18b89e1aae78a400a89c9d89423ce1da6a6a6964
This commit is contained in:
raf 2026-02-15 23:30:45 +03:00
commit f7081317ee
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
9 changed files with 245 additions and 96 deletions

View file

@ -292,8 +292,6 @@ pub struct RemoteBuilder {
pub created_at: DateTime<Utc>,
}
// --- User Management ---
/// User account for authentication and personalization
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct User {
@ -352,7 +350,7 @@ pub struct UserSession {
pub last_used_at: Option<DateTime<Utc>>,
}
// --- Pagination ---
// Pagination
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginationParams {
@ -389,7 +387,7 @@ pub struct PaginatedResponse<T> {
pub offset: i64,
}
// --- DTO structs for creation and updates ---
// DTO structs for creation and updates
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateProject {
@ -537,7 +535,7 @@ pub struct SystemStatus {
pub channels_count: i64,
}
// --- User DTOs ---
// User DTOs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateUser {

View file

@ -1,5 +1,7 @@
//! Notification dispatch for build events
use std::sync::OnceLock;
use tracing::{error, info, warn};
use crate::{
@ -7,6 +9,13 @@ use crate::{
models::{Build, BuildStatus, Project},
};
/// Shared HTTP client for all notification dispatches.
/// Avoids recreating connection pools on every build completion.
fn http_client() -> &'static reqwest::Client {
static CLIENT: OnceLock<reqwest::Client> = OnceLock::new();
CLIENT.get_or_init(reqwest::Client::new)
}
/// Dispatch all configured notifications for a completed build.
pub async fn dispatch_build_finished(
build: &Build,
@ -113,8 +122,7 @@ async fn set_github_status(
"context": format!("fc/{}", build.job_name),
});
let client = reqwest::Client::new();
match client
match http_client()
.post(&url)
.header("Authorization", format!("token {token}"))
.header("User-Agent", "fc-ci")
@ -166,8 +174,7 @@ async fn set_gitea_status(
"context": format!("fc/{}", build.job_name),
});
let client = reqwest::Client::new();
match client
match http_client()
.post(&url)
.header("Authorization", format!("token {token}"))
.json(&body)
@ -226,8 +233,7 @@ async fn set_gitlab_status(
"name": format!("fc/{}", build.job_name),
});
let client = reqwest::Client::new();
match client
match http_client()
.post(&url)
.header("PRIVATE-TOKEN", token)
.json(&body)

View file

@ -93,7 +93,7 @@ async fn create_test_build(
.expect("create build")
}
// ---- Existing tests ----
// CRUD and lifecycle tests
#[tokio::test]
async fn test_project_crud() {
@ -416,7 +416,7 @@ async fn test_not_found_errors() {
));
}
// ---- New hardening tests ----
// Batch operations and edge cases
#[tokio::test]
async fn test_batch_get_completed_by_drv_paths() {