Compare commits

...

1 commit

Author SHA1 Message Date
f1eaa440fc
feat: Add user resource w/database as storage 2025-01-08 19:09:57 +01:00
10 changed files with 758 additions and 23 deletions

View file

@ -1,6 +1,6 @@
nix_direnv_manual_reload
use flake
export DATABASE_URL=postgresql://patagia:swordfish@/patagia?host=$XDG_RUNTIME_DIR/patagia-postgres
export DATABASE_URL=postgresql://patagia:swordfish@patagia?host=$XDG_RUNTIME_DIR/patagia-postgres
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="http/protobuf"
export OTEL_RESOURCE_ATTRIBUTES=host.name=$HOSTNAME
export OTEL_SERVICE_NAME=$USER.patagia-control

676
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@ schemars.workspace = true
serde.workspace = true
slog-async.workspace = true
slog.workspace = true
sqlx = { version = "0.8.3", features = ["postgres", "runtime-tokio", "tls-rustls"] }
tokio.workspace = true
trace-request = { path = "../trace-request" }
tracing-slog.workspace = true

View file

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS patagia.public.Users(
id UUID PRIMARY KEY,
name VARCHAR(63) NOT NULL,
time_deleted TIMESTAMP WITH TIME ZONE, -- non-NULL if deleted
time_created TIMESTAMP WITH TIME ZONE NOT NULL,
time_modified TIMESTAMP WITH TIME ZONE NOT NULL
);

View file

@ -4,12 +4,14 @@ use dropshot::ApiDescription;
use std::sync::Arc;
use crate::context::ControllerContext;
use crate::user;
use crate::version;
type ControllerApiDescription = ApiDescription<Arc<ControllerContext>>;
pub fn api() -> Result<ControllerApiDescription> {
let mut api = ControllerApiDescription::new();
api.register(user::get_user_by_id)?;
api.register(version::version)?;
Ok(api)
}

View file

@ -1,8 +1,8 @@
use anyhow::{anyhow, Result};
use clap::Parser;
use dropshot::{ConfigDropshot, ServerBuilder};
use slog::Drain;
use sqlx::postgres::PgPool;
use tracing_slog::TracingSlogDrain;
use std::net::SocketAddr;
@ -30,12 +30,19 @@ struct Cli {
)]
log_stderr: bool,
#[arg(
long = "listen-address",
default_value = "0.0.0.0:9474",
env = "LISTEN_ADDRESS"
)]
listen_address: String,
#[arg(
long = "listen-address",
default_value = "0.0.0.0:9474",
env = "LISTEN_ADDRESS"
long = "database-url",
default_value = "postgresql://localhost/patagia",
env = "DATABASE_URL"
)]
listen_address: String,
database_url: Option<String>,
}
#[tokio::main]
@ -57,6 +64,12 @@ async fn main() -> Result<()> {
slog::Logger::root(async_drain, slog::o!())
};
let database_url = args.database_url.unwrap();
tracing::info!(database_url, listen_address=args.listen_address, "Starting server");
let _pool = PgPool::connect(&database_url).await?;
let ctx = ControllerContext::new();
let api = api::api()?;
ServerBuilder::new(api, Arc::new(ctx), logger)

View file

@ -1,4 +1,5 @@
pub mod api;
pub mod context;
mod user;
mod version;

46
controller/src/user.rs Normal file
View file

@ -0,0 +1,46 @@
use dropshot::{endpoint, HttpError, HttpResponseOk, Path, RequestContext};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use trace_request::trace_request;
use std::sync::Arc;
use crate::context::ControllerContext;
/// User
#[derive(Serialize, JsonSchema)]
struct User {
id: String,
name: String,
}
#[allow(dead_code)]
#[derive(Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
struct UsersPathParams {
user_id: String,
}
/// Fetch user info.
#[endpoint {
method = GET,
path = "/users/{userId}",
tags = [ "user" ],
}]
#[trace_request]
pub(crate) async fn get_user_by_id(
rqctx: RequestContext<Arc<ControllerContext>>,
params: Path<UsersPathParams>,
) -> Result<HttpResponseOk<User>, HttpError> {
let id = params.into_inner().user_id;
tracing::debug!(id, "Getting user by id");
let user = User {
id: "00000000-0000-0000-0000-000000000000".to_string(),
name: "Sune Testsson".to_string(),
};
Ok(HttpResponseOk(user))
}

View file

@ -141,6 +141,8 @@
just
nixfmt-rfc-style
rust-dev-toolchain
sqls
sqlx-cli
watchexec
]
++ commonArgs.buildInputs;

View file

@ -5,10 +5,12 @@ default:
@just --choose
# Run controller
[group('controller')]
run-controller $RUST_LOG="debug,h2=info,hyper_util=info,tower=info":
cargo run --package patagia-controller -- --log-stderr
# Run controller local development
[group('controller')]
dev-controller:
watchexec --clear --restart --stop-signal INT --debounce 300ms -- just run-controller
@ -56,6 +58,7 @@ check-nix:
nix flake check
# Run PostgreSQL for development and testing
[group('controller')]
dev-postgres:
mkdir -p "${XDG_RUNTIME_DIR}/patagia-postgres"
podman volume exists patagia-postgres || podman volume create patagia-postgres
@ -71,10 +74,28 @@ dev-postgres:
docker.io/postgres:17
# Clean up PostgreSQL data
[group('controller')]
dev-postgres-clean:
podman rm -f patagia-postgres || true
podman volume rm patagia-postgres || true
# Connect to PostgreSQL with psql
[group('controller')]
dev-postgres-psql:
podman exec -it patagia-postgres psql -U patagia
[group('controller')]
[working-directory: 'controller']
dev-controller-sqlx *ARGS:
sqlx {{ARGS}}
[group('controller')]
[working-directory: 'controller']
dev-controller-db-migrate:
sqlx migrate run
[group('controller')]
[working-directory: 'controller']
dev-controller-db-reset:
sqlx db reset -y