Basic minimal prototype

Use a postgres database as storage and start with sone basic
functionality.
This commit is contained in:
finga 2023-01-23 23:36:03 +01:00
commit 665015c296
14 changed files with 1082 additions and 0 deletions

88
src/main.rs Normal file
View file

@ -0,0 +1,88 @@
use anyhow::Result;
use diesel::{
prelude::*,
r2d2::{ConnectionManager, Pool, PooledConnection},
};
use lettre::{Message, SmtpTransport, Transport};
use std::{env, thread::park_timeout};
use time::{Duration, OffsetDateTime};
use tracing::{debug, info, trace};
mod models;
mod schema;
use models::{NewReminder, Reminder};
fn remind(
db: &mut PooledConnection<ConnectionManager<PgConnection>>,
mailer: &SmtpTransport,
) -> Result<()> {
debug!("executing remind run");
for reminder in schema::reminders::dsl::reminders
.filter(schema::reminders::executed.is_null())
.order(schema::reminders::planned.asc())
.load::<Reminder>(db)?
{
trace!(?reminder, "checking reminder");
if reminder.planned <= OffsetDateTime::now_utc() {
let email = Message::builder()
.from("whakarite@localhost".parse()?)
.to(reminder.receiver.parse()?)
.subject(&reminder.title)
.body(reminder.message.to_string())?;
mailer.send(&email)?;
diesel::update(&reminder)
.set(schema::reminders::executed.eq(Some(OffsetDateTime::now_utc())))
.execute(db)?;
debug!("email sent to {}", reminder.receiver);
} else {
info!(
"parking reminder for {:?}",
reminder.planned - OffsetDateTime::now_utc(),
);
park_timeout(<std::time::Duration>::try_from(
reminder.planned - OffsetDateTime::now_utc(),
)?);
}
// Check for another remnd job if none dont loop forever
}
Ok(())
}
fn main() -> Result<()> {
tracing_subscriber::fmt::init();
info!(
"{} {} started",
env!("CARGO_BIN_NAME"),
env!("CARGO_PKG_VERSION")
);
let db_pool = Pool::builder().build(ConnectionManager::<PgConnection>::new(
"postgresql://whakarite:whakarite@localhost/whakarite",
))?;
let test_reminder = NewReminder {
created: OffsetDateTime::now_utc(),
planned: (OffsetDateTime::now_utc() + Duration::MINUTE),
title: "Test title",
message: "Test message",
receiver: "finga@localhost",
};
diesel::insert_into(schema::reminders::table)
.values(&test_reminder)
.execute(&mut db_pool.get()?)?;
let mailer = SmtpTransport::unencrypted_localhost();
loop {
remind(&mut db_pool.get()?, &mailer)?;
}
}

24
src/models.rs Normal file
View file

@ -0,0 +1,24 @@
use crate::schema::reminders;
use diesel::prelude::*;
use time::OffsetDateTime;
#[derive(AsChangeset, Debug, Identifiable, Queryable)]
pub struct Reminder {
id: i32,
created: OffsetDateTime,
pub planned: OffsetDateTime,
executed: Option<OffsetDateTime>,
pub title: String,
pub message: String,
pub receiver: String,
}
#[derive(Insertable)]
#[diesel(table_name = reminders)]
pub struct NewReminder<'a> {
pub created: OffsetDateTime,
pub planned: OffsetDateTime,
pub title: &'a str,
pub message: &'a str,
pub receiver: &'a str,
}

13
src/schema.rs Normal file
View file

@ -0,0 +1,13 @@
// @generated automatically by Diesel CLI.
diesel::table! {
reminders (id) {
id -> Int4,
created -> Timestamptz,
planned -> Timestamptz,
executed -> Nullable<Timestamptz>,
title -> Text,
message -> Text,
receiver -> Text,
}
}