Started to implement proper event processing.

This commit is contained in:
didier amyot committed 2023-02-23 13:41:47 -05:00
1 parent af11915a52
commit 238cd9f2da
7 files changed
+74 -87

No files matched your search

+11 -42
View File
@@ -1,52 +1,21 @@
use std::borrow::Borrow; use rusqlite::{Connection, Transaction};
use std::fs::File;
use std::path::PathBuf;
use crate::events::{Bogus, CreateNewUser, Event};
use crate::util::{CustomResult, Error}; use crate::util::{CustomResult, Error};
use rusqlite::Connection; fn process_bogus_event(tx: &Transaction, event: Bogus) -> CustomResult<()> {
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug, PartialEq)]
struct CacheChequeEvent {
account: i64,
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
enum Event {
CacheCheque(CacheChequeEvent),
}
fn process_event_file(_conn: &mut Connection, _file: File) -> CustomResult<()> {
return Ok(());
}
pub fn process_event_files<I>(conn: &mut Connection, paths: I) -> CustomResult<()>
where
I: Iterator,
I::Item: Borrow<PathBuf>,
{
for path in paths {
let file = File::open(path.borrow()).map_err(Error::IOError)?;
process_event_file(conn, file)?;
}
Ok(()) Ok(())
} }
mod test { fn process_create_new_user_event(tx: &Transaction, event: CreateNewUser) -> CustomResult<()> {
use tempfile::tempfile; Ok(())
use super::*; }
pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> {
let tx = conn.transaction().map_err(Error::SqlError)?;
#[test] match event {
fn test_basic() -> CustomResult<()> { Event::Bogus(e) => process_bogus_event(&tx, e),
let file = tempfile().unwrap(); Event::CreateNewUser(e) => process_create_new_user_event(&tx, e),
let mut conn = Connection::open_in_memory().unwrap();
let ret = process_event_file(&mut conn, file);
ret
} }
} }
+20
View File
@@ -0,0 +1,20 @@
use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct Bogus {
pub name: String,
pub age: i64,
}
#[derive(Deserialize, Debug)]
pub struct CreateNewUser {
pub name: String,
pub score: i64,
}
#[derive(Deserialize, Debug)]
pub enum Event {
Bogus(Bogus),
CreateNewUser(CreateNewUser),
}
+5 -4
View File
@@ -10,7 +10,6 @@ use simple_logger::SimpleLogger;
use db::securities::list_securities; use db::securities::list_securities;
use crate::db::users::{create_user, list_users}; use crate::db::users::{create_user, list_users};
use crate::event_processor::process_event_files;
use crate::migration::apply_migrations; use crate::migration::apply_migrations;
use crate::util::{CustomResult, Error}; use crate::util::{CustomResult, Error};
use crate::webui::web_ui_main; use crate::webui::web_ui_main;
@@ -21,6 +20,7 @@ mod migration;
mod services; mod services;
mod util; mod util;
mod webui; mod webui;
mod events;
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
struct Output<T> { struct Output<T> {
@@ -516,17 +516,18 @@ impl CommandLineUserLogic for ProCommandLineLogic {
conn: &mut Connection, conn: &mut Connection,
files: ValuesRef<PathBuf>, files: ValuesRef<PathBuf>,
) -> CustomResult<()> { ) -> CustomResult<()> {
process_event_files(conn, files) // process_event_files(conn, files)
Ok(())
} }
fn run_webui( fn run_webui(
&mut self, &mut self,
_conn: &mut Connection, conn: &mut Connection,
port: u16, port: u16,
enable_template_autoreload: bool, enable_template_autoreload: bool,
) -> CustomResult<()> { ) -> CustomResult<()> {
info!("Serving web-ui on port {:?}", port); info!("Serving web-ui on port {:?}", port);
web_ui_main(port, enable_template_autoreload) web_ui_main(conn, port, enable_template_autoreload)
} }
} }
+1
View File
@@ -11,6 +11,7 @@ pub enum Error {
DoubleSpendingError(String), DoubleSpendingError(String),
IOError(io::Error), IOError(io::Error),
UserInputError(String), UserInputError(String),
FuckingError(String),
Testing(String), Testing(String),
} }
+14 -11
View File
@@ -4,19 +4,21 @@ use std::{env, path::PathBuf};
use actix_files; use actix_files;
use actix_web::{ use actix_web::{
App,
dev::ServiceResponse, dev::ServiceResponse,
error, error,
http::{header::ContentType, StatusCode}, FromRequest,
middleware::{ErrorHandlerResponse, ErrorHandlers, Logger}, http::{header::ContentType, StatusCode}, HttpRequest, HttpResponse, HttpServer, middleware::{ErrorHandlerResponse, ErrorHandlers, Logger}, Responder, Result, web,
web, App, FromRequest, HttpRequest, HttpResponse, HttpServer, Responder, Result,
}; };
use actix_web_lab::respond::Html; use actix_web_lab::respond::Html;
use async_channel; use async_channel;
use futures::{pin_mut, select, FutureExt}; use futures::{FutureExt, pin_mut, select};
use minijinja; use minijinja;
use minijinja_autoreload::AutoReloader; use minijinja_autoreload::AutoReloader;
use rusqlite::Connection;
use crate::util::CustomResult; use crate::events::Event;
use crate::util::{CustomResult, Error};
use crate::webui::worker::worker_loop; use crate::webui::worker::worker_loop;
mod views; mod views;
@@ -57,7 +59,9 @@ impl FromRequest for MiniJinjaRenderer {
} }
#[tokio::main] #[tokio::main]
pub async fn web_ui_main(port: u16, enable_template_autoreload: bool) -> CustomResult<()> { pub async fn web_ui_main(conn: &mut Connection,
port: u16,
enable_template_autoreload: bool) -> CustomResult<()> {
// The closure is invoked every time the environment is outdated to recreate it. // The closure is invoked every time the environment is outdated to recreate it.
let tmpl_reloader = AutoReloader::new(move |notifier| { let tmpl_reloader = AutoReloader::new(move |notifier| {
let mut env: minijinja::Environment<'static> = minijinja::Environment::new(); let mut env: minijinja::Environment<'static> = minijinja::Environment::new();
@@ -73,7 +77,7 @@ pub async fn web_ui_main(port: u16, enable_template_autoreload: bool) -> CustomR
Ok(env) Ok(env)
}); });
let (s, r) = async_channel::unbounded::<i32>(); let (s, r) = async_channel::unbounded::<Event>();
let tmpl_reloader = web::Data::new(tmpl_reloader); let tmpl_reloader = web::Data::new(tmpl_reloader);
@@ -98,14 +102,13 @@ pub async fn web_ui_main(port: u16, enable_template_autoreload: bool) -> CustomR
.unwrap(); .unwrap();
let t1 = server.run().fuse(); let t1 = server.run().fuse();
let t2 = worker_loop(r).fuse(); let t2 = worker_loop(conn, r).fuse();
pin_mut!(t1, t2); pin_mut!(t1, t2);
select! { select! {
x = t1 => x, x = t1 => x.map_err(Error::IOError),
y = t2 => y, y = t2 => y,
}; }
Ok(())
} }
/// Error handler for a 404 Page not found error. /// Error handler for a 404 Page not found error.
+10 -25
View File
@@ -1,12 +1,12 @@
use std::collections::HashMap;
use actix_web::{web, HttpRequest, Responder}; use actix_web::{error, HttpRequest, Responder, web};
use clap::builder::TypedValueParser; use clap::builder::TypedValueParser;
use log::info; use log::info;
use minijinja::context; use minijinja::context;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap;
use crate::events::Event;
use crate::webui::MiniJinjaRenderer; use crate::webui::MiniJinjaRenderer;
#[actix_web::get("/")] #[actix_web::get("/")]
@@ -52,23 +52,6 @@ pub async fn actions_partials(
tmpl_env.render(template_location.as_str(), ctx) tmpl_env.render(template_location.as_str(), ctx)
} }
#[derive(Deserialize, Debug)]
struct Event1 {
name: String,
age: i64,
}
#[derive(Deserialize, Debug)]
struct Event2 {
name: String,
score: i64,
}
#[derive(Deserialize, Debug)]
enum Event {
Event1(Event1),
Event2(Event2),
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
struct CreateEventPayload { struct CreateEventPayload {
@@ -80,14 +63,16 @@ struct CreateEventPayload {
pub async fn push_event( pub async fn push_event(
req: HttpRequest, req: HttpRequest,
tmpl_env: MiniJinjaRenderer, tmpl_env: MiniJinjaRenderer,
event_channel: web::Data<async_channel::Sender<i32>>, event_channel: web::Data<async_channel::Sender<Event>>,
web::Json(form): web::Json<CreateEventPayload>, web::Json(form): web::Json<CreateEventPayload>,
) -> actix_web::Result<impl Responder> { ) -> actix_web::Result<impl Responder> {
let shit = req.match_info().get("event_type").unwrap(); let path_event_type = req.match_info().get("event_type").unwrap();
println!("payload: {:?}", form); if path_event_type.to_string() != form.event_type {
let _ = event_channel.send(56).await; return Err(error::ErrorBadRequest("Inconsistent event type."))
}
let _ = event_channel.send(form.event).await;
let ctx = context! { let ctx = context! {
event_type => shit, event_type => "bob le chef",
}; };
tmpl_env.render("partials/v1/event_processed.html", ctx) tmpl_env.render("partials/v1/event_processed.html", ctx)
} }
+13 -5
View File
@@ -1,13 +1,21 @@
use std::io; use std::io;
pub async fn worker_loop(r: async_channel::Receiver<i32>) -> io::Result<()> { use rusqlite::Connection;
use crate::event_processor::process_event;
use crate::events::Event;
use crate::util::CustomResult;
use crate::util::Error::FuckingError;
pub async fn worker_loop(conn: &mut Connection,
r: async_channel::Receiver<Event>) -> CustomResult<()> {
loop { loop {
let x = r.recv().await; let res = r.recv().await;
match x { match res {
Ok(v) => println!("Processed value: {:?}", v), Ok(event) => process_event(conn, event)?, // todo, remove ?
Err(e) => { Err(e) => {
println!("Error: {:?}", e); println!("Error: {:?}", e);
return Ok(()); return Err(FuckingError(e.to_string()));
} }
} }
} }