fix tests and properly intgrate sqlx
Some checks failed
Backend Actions / check (push) Failing after 3m26s
Frontend Actions / check (push) Failing after 3m17s
Backend Actions / test (push) Failing after 3m20s
Frontend Actions / test (push) Successful in 51s
Frontend Actions / build (push) Successful in 56s
Backend Actions / build (push) Failing after 10m57s
Some checks failed
Backend Actions / check (push) Failing after 3m26s
Frontend Actions / check (push) Failing after 3m17s
Backend Actions / test (push) Failing after 3m20s
Frontend Actions / test (push) Successful in 51s
Frontend Actions / build (push) Successful in 56s
Backend Actions / build (push) Failing after 10m57s
This commit is contained in:
152
backend/Cargo.lock
generated
152
backend/Cargo.lock
generated
@ -32,6 +32,21 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.19"
|
||||
@ -258,6 +273,21 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.41"
|
||||
@ -575,6 +605,21 @@ version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
@ -619,6 +664,17 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.31"
|
||||
@ -637,8 +693,10 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
@ -809,7 +867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
|
||||
dependencies = [
|
||||
"bytes 0.4.12",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
"http 0.1.21",
|
||||
"tokio-buf",
|
||||
]
|
||||
@ -938,6 +996,30 @@ dependencies = [
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.0.0"
|
||||
@ -1334,12 +1416,15 @@ name = "nuchat"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"clap",
|
||||
"futures 0.3.31",
|
||||
"http 1.3.1",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tap",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http",
|
||||
@ -2111,6 +2196,7 @@ checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes 1.10.1",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crossbeam-queue",
|
||||
"either",
|
||||
@ -2135,6 +2221,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2186,6 +2273,7 @@ dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"byteorder",
|
||||
"bytes 1.10.1",
|
||||
"chrono",
|
||||
"crc",
|
||||
"digest",
|
||||
"dotenvy",
|
||||
@ -2214,6 +2302,7 @@ dependencies = [
|
||||
"stringprep",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"whoami",
|
||||
]
|
||||
|
||||
@ -2227,6 +2316,7 @@ dependencies = [
|
||||
"base64",
|
||||
"bitflags 2.9.1",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"crc",
|
||||
"dotenvy",
|
||||
"etcetera",
|
||||
@ -2251,6 +2341,7 @@ dependencies = [
|
||||
"stringprep",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"whoami",
|
||||
]
|
||||
|
||||
@ -2261,6 +2352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"chrono",
|
||||
"flume",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
@ -2276,6 +2368,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2359,6 +2452,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.20.0"
|
||||
@ -2454,7 +2553,7 @@ checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
|
||||
dependencies = [
|
||||
"bytes 0.4.12",
|
||||
"either",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2464,7 +2563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2474,7 +2573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
|
||||
dependencies = [
|
||||
"bytes 0.4.12",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -2506,7 +2605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mio 0.6.23",
|
||||
@ -2546,7 +2645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2556,7 +2655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
|
||||
dependencies = [
|
||||
"bytes 0.4.12",
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
"iovec",
|
||||
"mio 0.6.23",
|
||||
"tokio-io",
|
||||
@ -2625,7 +2724,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442ba79e23bda499cdaa5ee52b3776bf08cb84a1d5ca6d3d82bfd4f12c1eefc3"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
"http 0.1.21",
|
||||
"http-body 0.1.0",
|
||||
"http-connection",
|
||||
@ -2646,7 +2745,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cc0c98637d23732f8de6dfd16494c9f1559c3b9e20b4a46462c8f9b9e827bfa"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"futures 0.1.31",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2970,6 +3069,41 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
|
||||
@ -4,12 +4,15 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
axum = "0.8.4"
|
||||
axum = { version = "0.8.4", features = [] }
|
||||
chrono = { version = "0.4.41", features = ["serde"] }
|
||||
clap = { version = "4.5.41", features = ["derive"] }
|
||||
futures = "0.3.31"
|
||||
http = "1.3.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.141"
|
||||
sqlx = { version = "0.8.6", features = ["postgres", "macros", "runtime-tokio"] }
|
||||
sqlx = { version = "0.8.6", features = ["postgres", "macros", "runtime-tokio", "uuid", "chrono"] }
|
||||
tap = "1.0.1"
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
tower = { version = "0.5.2", features = ["full"] }
|
||||
tower-http = { version = "0.6.6", features = ["timeout", "trace", "auth", "request-id"] }
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
-- Add migration script here
|
||||
CREATE TABLE servers (
|
||||
id uuid NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
name TEXT NOT NULL,
|
||||
created_at timestamptz NOT NULL
|
||||
)
|
||||
@ -0,0 +1,7 @@
|
||||
-- Add migration script here
|
||||
CREATE TABLE messages (
|
||||
id uuid NOT NULL,
|
||||
PRIMARY KEY(id),
|
||||
contents TEXT NOT NULL,
|
||||
created_at timestamptz NOT NULL
|
||||
)
|
||||
@ -1,2 +0,0 @@
|
||||
DROP DATABASE IF EXISTS nuchat_test;
|
||||
CREATE DATABASE nuchat_test;
|
||||
@ -8,13 +8,26 @@ if ! command -v cargo-nextest > /dev/null 2>&1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
psql "$POSTGRES_URL" -f ./scripts/create_test_db.sql
|
||||
|
||||
if [ "$?" -ne "0" ]; then
|
||||
echo "Unable to connect to database, make sure it is started"
|
||||
if ! command -v sqlx > /dev/null 2>&1; then
|
||||
echo "Command not found sqlx"
|
||||
echo "Try installing with cargo install sqlx-cli"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export DATABASE_URL="$POSTGRES_URL/nuchat_dev"
|
||||
|
||||
if [ -z "$SKIP_DOCKER" ]; then
|
||||
# force restart database so no connections
|
||||
# prevent database from being dropped
|
||||
docker compose -f ../docker-compose.yml down
|
||||
docker compose -f ../docker-compose.yml up -d db
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# recreate database and tables
|
||||
sqlx database drop -y
|
||||
sqlx database create
|
||||
sqlx migrate run
|
||||
|
||||
if [ ! -d logs ]; then
|
||||
mkdir logs
|
||||
@ -24,7 +37,8 @@ fi
|
||||
curl -s -X POST localhost:7001/admin/shutdown 2>&1 > /dev/null
|
||||
|
||||
# start server
|
||||
cargo run -- --port 7001 --postgres-url "$POSTGRES_URL" 2>&1 > logs/nuchat.log &
|
||||
cargo run -- --port 7001 --postgres-url "$POSTGRES_URL" --database "nuchat_dev" 2>&1 > logs/nuchat.log &
|
||||
|
||||
sleep 1
|
||||
# run tests
|
||||
cargo nextest run --color=always 2>&1 | tee logs/test-output.log
|
||||
cargo nextest run --color=always --no-fail-fast 2>&1 | tee logs/test-output.log
|
||||
|
||||
@ -28,7 +28,7 @@ struct Args {
|
||||
admin_secret: Option<String>,
|
||||
|
||||
/// postgres base url, should container users and host info
|
||||
#[arg(long, default_value = "postgres://postgres:postgres@localhost:5432/")]
|
||||
#[arg(long, default_value = "postgres://postgres:postgres@localhost:5432")]
|
||||
postgres_url: String,
|
||||
|
||||
/// name of database to use
|
||||
@ -49,7 +49,9 @@ async fn main() {
|
||||
.with(tracing_subscriber::fmt::layer().with_target(false))
|
||||
.init();
|
||||
|
||||
let pool = Pool::<Postgres>::connect(&config.0.postgres_url)
|
||||
let database_url = format!("{}/{}", config.0.postgres_url, config.0.database_name);
|
||||
info!("Connecting to database: {database_url}");
|
||||
let pool = Pool::<Postgres>::connect(&database_url)
|
||||
.await
|
||||
.expect("Could not connect to database");
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
mod admin;
|
||||
mod healthcheck;
|
||||
mod messages;
|
||||
mod servers;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -32,7 +34,16 @@ pub fn app(state: &AppState) -> (Router<AppState>, mpsc::Receiver<bool>) {
|
||||
Router::new()
|
||||
.with_state(state.clone())
|
||||
.route("/healthcheck", get(healthcheck::healthcheck))
|
||||
.route("/forever", get(std::future::pending::<()>))
|
||||
.route(
|
||||
"/servers",
|
||||
get(servers::get_servers).post(servers::create_server),
|
||||
)
|
||||
.route("/servers/{id}", get(servers::get_server_by_id))
|
||||
.route(
|
||||
"/messages",
|
||||
get(messages::get_messages).post(messages::create_message),
|
||||
)
|
||||
.route("/messages/{id}", get(messages::get_message_by_id))
|
||||
.nest("/admin", admin::router(tx, state))
|
||||
.layer(
|
||||
ServiceBuilder::new()
|
||||
|
||||
@ -41,7 +41,7 @@ mod test {
|
||||
let state = AppState::new(NuState::new(
|
||||
pool,
|
||||
Config {
|
||||
database_name: String::from("nuchat_test"),
|
||||
database_name: String::from("nuchat_dev"),
|
||||
..Config::default()
|
||||
},
|
||||
));
|
||||
|
||||
68
backend/src/router/messages.rs
Normal file
68
backend/src/router/messages.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use axum::{
|
||||
Form, Json,
|
||||
body::Body,
|
||||
extract::{Path, State},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use http::StatusCode;
|
||||
use sqlx::types::chrono;
|
||||
use tracing::info;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||
pub struct Message {
|
||||
pub contents: String,
|
||||
pub id: Uuid,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CreateMessage {
|
||||
pub contents: String,
|
||||
}
|
||||
|
||||
pub async fn get_messages(State(s): State<AppState>) -> Result<Json<Vec<Message>>, StatusCode> {
|
||||
sqlx::query_as!(Message, r#"SELECT id, contents, created_at FROM messages"#)
|
||||
.fetch_all(&s.db)
|
||||
.await
|
||||
.map(Json)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
||||
pub async fn create_message(
|
||||
State(s): State<AppState>,
|
||||
Form(message): Form<CreateMessage>,
|
||||
) -> Result<Response<Body>, StatusCode> {
|
||||
info!("Creating new message with name: {}", message.contents);
|
||||
let id = Uuid::now_v7();
|
||||
|
||||
sqlx::query!(
|
||||
r"INSERT INTO messages (id, contents, created_at) VALUES($1, $2, current_timestamp) RETURNING id",
|
||||
id,
|
||||
message.contents
|
||||
).fetch_one(&s.db).await
|
||||
.map(|row| {
|
||||
let mut resp = Json(row.id).into_response();
|
||||
let status = resp.status_mut();
|
||||
*status = StatusCode::CREATED;
|
||||
info!("Successfully created message Message[{}, {}]", row.id, message.contents);
|
||||
resp
|
||||
}).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
||||
pub async fn get_message_by_id(
|
||||
Path(id): Path<Uuid>,
|
||||
State(s): State<AppState>,
|
||||
) -> Result<Json<Message>, StatusCode> {
|
||||
sqlx::query_as!(
|
||||
Message,
|
||||
r#"SELECT id, contents, created_at FROM messages WHERE id = $1"#,
|
||||
id
|
||||
)
|
||||
.fetch_optional(&s.db)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.and_then(|mayber_message| mayber_message.map(Json).ok_or(StatusCode::NOT_FOUND))
|
||||
}
|
||||
68
backend/src/router/servers.rs
Normal file
68
backend/src/router/servers.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use axum::{
|
||||
Form, Json,
|
||||
body::Body,
|
||||
extract::{Path, State},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use http::StatusCode;
|
||||
use sqlx::types::chrono;
|
||||
use tracing::info;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||
pub struct Server {
|
||||
pub name: String,
|
||||
pub id: Uuid,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct CreateServer {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub async fn get_servers(State(s): State<AppState>) -> Result<Json<Vec<Server>>, StatusCode> {
|
||||
sqlx::query_as!(Server, r#"SELECT id, name, created_at FROM servers"#)
|
||||
.fetch_all(&s.db)
|
||||
.await
|
||||
.map(Json)
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
||||
pub async fn create_server(
|
||||
State(s): State<AppState>,
|
||||
Form(server): Form<CreateServer>,
|
||||
) -> Result<Response<Body>, StatusCode> {
|
||||
info!("Creating new server with name: {}", server.name);
|
||||
let id = Uuid::now_v7();
|
||||
|
||||
sqlx::query!(
|
||||
r"INSERT INTO servers (id, name, created_at) VALUES($1, $2, current_timestamp) RETURNING id",
|
||||
id,
|
||||
server.name
|
||||
).fetch_one(&s.db).await
|
||||
.map(|row| {
|
||||
let mut resp = Json(row.id).into_response();
|
||||
let status = resp.status_mut();
|
||||
*status = StatusCode::CREATED;
|
||||
info!("Successfully created server Server[{}, {}]", row.id, server.name);
|
||||
resp
|
||||
}).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
||||
pub async fn get_server_by_id(
|
||||
Path(id): Path<Uuid>,
|
||||
State(s): State<AppState>,
|
||||
) -> Result<Json<Server>, StatusCode> {
|
||||
sqlx::query_as!(
|
||||
Server,
|
||||
r#"SELECT id, name, created_at FROM servers WHERE id = $1"#,
|
||||
id
|
||||
)
|
||||
.fetch_optional(&s.db)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.and_then(|mayber_server| mayber_server.map(Json).ok_or(StatusCode::NOT_FOUND))
|
||||
}
|
||||
Reference in New Issue
Block a user