Add database functions for inserting history

No real tests yet :( I would like to avoid running postgres lol
This commit is contained in:
Ellie Huxtable
2023-06-26 08:09:00 +01:00
parent 5eb07c722e
commit fd51031bde
4 changed files with 53 additions and 1 deletions

View File

@ -13,7 +13,7 @@ use self::{
models::{History, NewHistory, NewSession, NewUser, Session, User},
};
use async_trait::async_trait;
use atuin_common::utils::get_days_from_month;
use atuin_common::{record::Record, utils::get_days_from_month};
use chrono::{Datelike, TimeZone};
use chronoutil::RelativeDuration;
use serde::{de::DeserializeOwned, Serialize};
@ -55,6 +55,11 @@ pub trait Database: Sized + Clone + Send + Sync + 'static {
async fn delete_history(&self, user: &User, id: String) -> DbResult<()>;
async fn deleted_history(&self, user: &User) -> DbResult<Vec<String>>;
async fn add_record(&self, user: &User, record: &[Record]) -> DbResult<()>;
// Return the tail record ID for each store, so (HostID, Tag, TailRecordID)
async fn tail_records(&self, user: &User) -> DbResult<Vec<(String, String, String)>>;
async fn count_history_range(
&self,
user: &User,

View File

@ -1,6 +1,7 @@
-- Add migration script here
create table records (
id uuid primary key, -- remember to use uuidv7 for happy indices <3
client_id uuid not null, -- I am too uncomfortable with the idea of a client-generated primary key
host uuid not null, -- a unique identifier for the host
parent uuid not null, -- the ID of the parent record, bearing in mind this is a linked list
timestamp bigint not null, -- not a timestamp type, as those do not have nanosecond precision

View File

@ -1,4 +1,5 @@
use async_trait::async_trait;
use atuin_common::record::Record;
use atuin_server_database::models::{History, NewHistory, NewSession, NewUser, Session, User};
use atuin_server_database::{Database, DbError, DbResult};
use futures_util::TryStreamExt;
@ -329,4 +330,49 @@ impl Database for Postgres {
.map_err(fix_error)
.map(|DbHistory(h)| h)
}
async fn add_record(&self, user: &User, records: &[Record]) -> DbResult<()> {
let mut tx = self.pool.begin().await.map_err(fix_error)?;
for i in records {
let id = atuin_common::utils::uuid_v7().as_simple().to_string();
sqlx::query(
"insert into records
(id, client_id, host, parent, timestamp, version, tag, data, user_id)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
on conflict do nothing
",
)
.bind(id)
.bind(&i.id)
.bind(&i.host)
.bind(&i.parent)
.bind(i.timestamp as i64) // throwing away some data, but i64 is still big in terms of time
.bind(&i.version)
.bind(&i.tag)
.bind(&i.data)
.bind(user.id)
.execute(&mut tx)
.await
.map_err(fix_error)?;
}
tx.commit().await.map_err(fix_error)?;
Ok(())
}
async fn tail_records(&self, user: &User) -> DbResult<Vec<(String, String, String)>> {
const TAIL_RECORDS_SQL: &str = "select host, tag, id from records rp where (select count(1) from records where parent=rp.id and user_id = $1) = 0 group by host, tag;";
let res = sqlx::query_as(TAIL_RECORDS_SQL)
.bind(user.id)
.fetch(&self.pool)
.try_collect()
.await
.map_err(fix_error)?;
Ok(res)
}
}

View File