Listening to the shaggs!

This commit is contained in:
didier amyot committed 2023-02-24 08:52:50 -05:00
1 parent 238cd9f2da
commit 9f86d53d11
9 files changed
+65 -62

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+4 -1
View File
@@ -16,7 +16,10 @@
<nav class="uk-navbar-container" uk-navbar> <nav class="uk-navbar-container" uk-navbar>
<div class="uk-navbar-left"> <div class="uk-navbar-left">
<a href="/" class="uk-navbar-item uk-logo">Ledger</a> <a href="/" class="uk-navbar-item uk-logo uk-margin-medium-left">
<img src="/static/images/33-game-robot.png" class="uk-margin-medium" style="height: 1em;">
Ledger
</a>
<ul class="uk-navbar-nav"> <ul class="uk-navbar-nav">
{% set nav_bar_items = [{'id': 'overview', 'label': 'Overview'}, {% set nav_bar_items = [{'id': 'overview', 'label': 'Overview'},
{'id': 'actions', 'label': 'Actions'}]%} {'id': 'actions', 'label': 'Actions'}]%}
+7 -13
View File
@@ -1,18 +1,12 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block body %} {% block body %}
<h2>Securities</h2>
<table class="uk-table"> <div class="uk-flex-center" uk-grid>
<thead> <div style="text-align: center;">
<tr> <h3 class="uk-h3">Our goal: to not be your stupidest investment option.</h3>
<th>Security</th> <img src="/static/images/33-game-robot.png" style="height: 50%">
</tr> </div>
</thead> </div>
<tbody>
<tr>
<td>UAD</td>
</tr>
</tbody>
</table>
{% endblock %} {% endblock %}
@@ -1,14 +1,14 @@
<div class="uk-margin"> <div class="uk-margin">
<label class="uk-form-label"> Name <label class="uk-form-label"> Name
<input class="uk-input" type="text" placeholder="Caroline Ellison" aria-label="Default" <input class="uk-input" type="text" placeholder="Caroline Ellison" aria-label="Default"
name="event.NewUser.name"> name="event.CreateNewUser.name">
</label> </label>
</div> </div>
<div class="uk-margin"> <div class="uk-margin">
<label class="uk-form-label"> Public Key <label class="uk-form-label"> Public Key
<input class="uk-input" type="text" placeholder="xxxxx" aria-label="Default" <input class="uk-input" type="text" placeholder="xxxxx" aria-label="Default"
name="event.NewUser.PublicKey"> name="event.CreateNewUser.public_key">
</label> </label>
</div> </div>
+10 -8
View File
@@ -1,21 +1,23 @@
use rusqlite::{Connection, Transaction}; use rusqlite::{Connection, Transaction};
use crate::events::{Bogus, CreateNewUser, Event}; use crate::db::users::create_user;
use crate::events::{CreateNewSecurity, CreateNewUser, Event};
use crate::util::{CustomResult, Error}; use crate::util::{CustomResult, Error};
fn process_bogus_event(tx: &Transaction, event: Bogus) -> CustomResult<()> { fn process_bogus_event(tx: &Transaction, event: CreateNewSecurity) -> CustomResult<()> {
Ok(()) Ok(())
} }
fn process_create_new_user_event(tx: &Transaction, event: CreateNewUser) -> CustomResult<()> { fn process_create_new_user_event(tx: &mut Transaction, event: CreateNewUser) -> CustomResult<()> {
create_user(&tx, &event.name, &event.public_key)?;
Ok(()) Ok(())
} }
pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> { pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> {
let tx = conn.transaction().map_err(Error::SqlError)?; let mut tx = conn.transaction().map_err(Error::SqlError)?;
match event { match event {
Event::Bogus(e) => process_bogus_event(&tx, e), Event::CreateNewSecurity(e) => process_bogus_event(&mut tx, e)?,
Event::CreateNewUser(e) => process_create_new_user_event(&tx, e), Event::CreateNewUser(e) => process_create_new_user_event(&mut tx, e)?,
} };
tx.commit().map_err(Error::SqlError)
} }
+3 -3
View File
@@ -2,7 +2,7 @@ use serde::Deserialize;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct Bogus { pub struct CreateNewSecurity {
pub name: String, pub name: String,
pub age: i64, pub age: i64,
} }
@@ -10,11 +10,11 @@ pub struct Bogus {
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct CreateNewUser { pub struct CreateNewUser {
pub name: String, pub name: String,
pub score: i64, pub public_key: String,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub enum Event { pub enum Event {
Bogus(Bogus), CreateNewSecurity(CreateNewSecurity),
CreateNewUser(CreateNewUser), CreateNewUser(CreateNewUser),
} }
+4 -23
View File
@@ -17,22 +17,15 @@ pub enum Error {
pub type CustomResult<T, E = Error> = Result<T, E>; pub type CustomResult<T, E = Error> = Result<T, E>;
trait SQLiteConnectionFactory { pub struct SQLiteConnectionFactory {
fn connection(&self) -> Connection;
fn readonly(&self) -> Connection;
}
pub struct PathSQLiteConnectionFactory {
path: String, path: String,
} }
impl PathSQLiteConnectionFactory { impl SQLiteConnectionFactory {
pub fn new(path: String) -> PathSQLiteConnectionFactory { pub fn new(path: String) -> SQLiteConnectionFactory {
PathSQLiteConnectionFactory { path } SQLiteConnectionFactory { path }
}
} }
impl SQLiteConnectionFactory for PathSQLiteConnectionFactory {
fn connection(&self) -> Connection { fn connection(&self) -> Connection {
Connection::open(&self.path).unwrap() Connection::open(&self.path).unwrap()
} }
@@ -41,15 +34,3 @@ impl SQLiteConnectionFactory for PathSQLiteConnectionFactory {
Connection::open_with_flags(&self.path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap() Connection::open_with_flags(&self.path, OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap()
} }
} }
pub struct InMemorySQLiteConnectionFactory {}
impl SQLiteConnectionFactory for InMemorySQLiteConnectionFactory {
fn connection(&self) -> Connection {
Connection::open_in_memory().unwrap()
}
fn readonly(&self) -> Connection {
Connection::open_in_memory_with_flags(OpenFlags::SQLITE_OPEN_READ_ONLY).unwrap()
}
}
+24 -10
View File
@@ -19,11 +19,19 @@ use rusqlite::Connection;
use crate::events::Event; use crate::events::Event;
use crate::util::{CustomResult, Error}; use crate::util::{CustomResult, Error};
use crate::webui::worker::worker_loop; use crate::webui::worker::{bob, event_processor_loop};
mod views; mod views;
mod worker; mod worker;
struct Service {}
impl Service {
fn get_users(self) -> Vec<String> {
vec!["to".to_string(), "foo".to_string()]
}
}
struct MiniJinjaRenderer { struct MiniJinjaRenderer {
tmpl_env: web::Data<minijinja_autoreload::AutoReloader>, tmpl_env: web::Data<minijinja_autoreload::AutoReloader>,
} }
@@ -58,12 +66,8 @@ impl FromRequest for MiniJinjaRenderer {
} }
} }
#[tokio::main] fn create_auto_reloader(enable_template_autoreload: bool) -> AutoReloader {
pub async fn web_ui_main(conn: &mut Connection, AutoReloader::new(move |notifier| {
port: u16,
enable_template_autoreload: bool) -> CustomResult<()> {
// The closure is invoked every time the environment is outdated to recreate it.
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();
let tmpl_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/templates"); let tmpl_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("resources/templates");
@@ -75,7 +79,15 @@ pub async fn web_ui_main(conn: &mut Connection,
} }
env.set_source(minijinja::Source::from_path(tmpl_path)); env.set_source(minijinja::Source::from_path(tmpl_path));
Ok(env) Ok(env)
}); })
}
#[tokio::main]
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.
let tmpl_reloader = create_auto_reloader(enable_template_autoreload);
let (s, r) = async_channel::unbounded::<Event>(); let (s, r) = async_channel::unbounded::<Event>();
@@ -102,12 +114,14 @@ pub async fn web_ui_main(conn: &mut Connection,
.unwrap(); .unwrap();
let t1 = server.run().fuse(); let t1 = server.run().fuse();
let t2 = worker_loop(conn, r).fuse(); let t2 = event_processor_loop(conn, r).fuse();
pin_mut!(t1, t2); let t3 = bob().fuse();
pin_mut!(t1, t2, t3);
select! { select! {
x = t1 => x.map_err(Error::IOError), x = t1 => x.map_err(Error::IOError),
y = t2 => y, y = t2 => y,
z = t3 => z,
} }
} }
+11 -2
View File
@@ -1,18 +1,20 @@
use std::io; use std::io;
use std::time::Duration;
use rusqlite::Connection; use rusqlite::Connection;
use tokio::time::sleep;
use crate::event_processor::process_event; use crate::event_processor::process_event;
use crate::events::Event; use crate::events::Event;
use crate::util::CustomResult; use crate::util::CustomResult;
use crate::util::Error::FuckingError; use crate::util::Error::FuckingError;
pub async fn worker_loop(conn: &mut Connection, pub async fn event_processor_loop(conn: &mut Connection,
r: async_channel::Receiver<Event>) -> CustomResult<()> { r: async_channel::Receiver<Event>) -> CustomResult<()> {
loop { loop {
let res = r.recv().await; let res = r.recv().await;
match res { match res {
Ok(event) => process_event(conn, event)?, // todo, remove ? Ok(event) => process_event(conn, event)?, // todo, remove "?"
Err(e) => { Err(e) => {
println!("Error: {:?}", e); println!("Error: {:?}", e);
return Err(FuckingError(e.to_string())); return Err(FuckingError(e.to_string()));
@@ -20,3 +22,10 @@ pub async fn worker_loop(conn: &mut Connection,
} }
} }
} }
pub async fn bob() -> CustomResult<()> {
loop {
sleep(Duration::from_millis(1000)).await;
println!("100 ms have elapsed");
}
}