grimhilde/ingest/src/db.rs

60 lines
1.7 KiB
Rust

// grimhilde - mirror stats
// Copyright (C) 2022 Amanda Graven and Emelie Graven
// Licensed under the EUPL
//
use std::error::Error as StdError;
use sqlx::PgPool;
use crate::Request;
/// Connect to a postgress address.
pub async fn connect(address: &str) -> sqlx::Result<PgPool> {
let pool = PgPool::connect(address).await?;
sqlx::migrate!().run(&pool).await?;
Ok(pool)
}
/// Insert a request hit into the database
pub async fn insert(pool: &PgPool, req: Request) -> Result<(), Box<dyn StdError>> {
let mut trans = pool.begin().await?;
// Get the id's for deduplicated values. Insert a value if one is missing.
let path_id = sqlx::query!(
"INSERT INTO paths (path) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id",
&req.path,
).fetch_one(&mut *trans).await?.id;
let remote_id = sqlx::query!(
"INSERT INTO remote_addresses (addr) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id",
req.addr)
.fetch_one(&mut *trans).await?.id;
let host_id = sqlx::query!(
"INSERT INTO hosts (host) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id",
&req.host)
.fetch_one(&mut *trans).await?.id;
let user_agent_id = sqlx::query!(
"INSERT INTO user_agents (agent) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id",
&req.user_agent,
).fetch_one(&mut *trans).await?.id;
let referrer_id = sqlx::query!(
"INSERT INTO referrers (referrer) VALUES ($1) ON CONFLICT DO NOTHING RETURNING id",
&req.referrer,
).fetch_one(&mut *trans).await?.id;
sqlx::query!(
"INSERT INTO hits (size, path, remote, host, user_agent, referrer, secure, time) \
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)",
req.size,
path_id,
remote_id,
host_id,
user_agent_id,
referrer_id,
req.secure,
req.timestamp,
).execute(&mut *trans).await?;
trans.commit().await?;
Ok(())
}