wip: still working torwards the Redis oriented arch.

This commit is contained in:
meeg_leeto 2022-04-14 13:33:32 +01:00
parent 703a52ea8f
commit 1cc260b998
6 changed files with 60 additions and 12 deletions

View File

@ -8,7 +8,7 @@ WORKDIR lonk
COPY ./Cargo.lock ./Cargo.lock COPY ./Cargo.lock ./Cargo.lock
COPY ./Cargo.toml ./Cargo.toml COPY ./Cargo.toml ./Cargo.toml
RUN cargo build --release RUN cargo build
RUN src/*.rs RUN src/*.rs
# Compile the source # Compile the source

View File

@ -1,12 +1,12 @@
{ {
"db": { "db": {
"address": "redis://127.0.0.1" "address": "redis://db"
}, },
"slug_rules": { "slug_rules": {
"length": 5, "length": 5,
"chars": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" "chars": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
}, },
"serve_rules": { "serve_rules": {
"Dir": "/etc/lonk/served" "Dir": "/data/served"
} }
} }

13
data/served/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Lonk</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
</body>
</html>

0
data/served/main.css Normal file
View File

View File

@ -3,8 +3,8 @@ services:
lonk: lonk:
build: . build: .
environment: environment:
- PROFILE: release
- LONK_CONFIG: /data/config.json - LONK_CONFIG: /data/config.json
- PROFILE: debug
volumes: volumes:
- ./data:/data - ./data:/data
redis: redis:

View File

@ -1,8 +1,8 @@
use argh::FromArgs; use argh::FromArgs;
use figment::{providers::Format, Figment}; use figment::{providers::Format, Figment};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::BTreeSet, path::PathBuf, str::FromStr, sync::Arc}; use std::{collections::BTreeSet, path::PathBuf, str::FromStr, sync::Arc, io::BufRead};
use tokio::sync::mpsc::UnboundedSender; use tokio::{sync};
use validators::prelude::*; use validators::prelude::*;
use warp::{filters::BoxedFilter, hyper::StatusCode, Filter}; use warp::{filters::BoxedFilter, hyper::StatusCode, Filter};
@ -15,6 +15,16 @@ macro_rules! unwrap_or_unwrap_err {
}; };
} }
macro_rules! clone_to_move {
($($y:ident),+$x:ident) => {
clone_to_move!($x);
clone_to_move!($y)
};
($x:ident) => {
let $x = $x.clone();
};
}
#[derive(Serialize, Deserialize, Debug, Validator, Clone)] #[derive(Serialize, Deserialize, Debug, Validator, Clone)]
#[validator(domain(ipv4(Allow), local(Allow), at_least_two_labels(Allow), port(Allow)))] #[validator(domain(ipv4(Allow), local(Allow), at_least_two_labels(Allow), port(Allow)))]
struct Url { struct Url {
@ -25,12 +35,14 @@ struct Url {
#[derive(Deserialize, Serialize, Debug, Clone)] #[derive(Deserialize, Serialize, Debug, Clone)]
struct DbConfig { struct DbConfig {
pub address: String, pub address: String,
pub worker_threads: usize,
} }
impl Default for DbConfig { impl Default for DbConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
address: "redis://127.0.0.1".to_string(), address: "redis://127.0.0.1".to_string(),
worker_threads: 4,
} }
} }
} }
@ -102,17 +114,40 @@ impl FromStr for Base64WithoutPaddingUrl {
#[derive(Debug)] #[derive(Debug)]
struct SlugDatabase { struct SlugDatabase {
tx: UnboundedSender<SlugDbMessage>, tx: sync::mpsc::UnboundedSender<SlugDbMessage>,
} }
#[derive(Debug)] #[derive(Clone, Debug)]
enum SlugDbMessage { enum SlugDbMessage {
Add(Slug, Url), Add(Slug, Url),
} }
impl SlugDatabase { impl SlugDatabase {
fn from_client(client: redis::Client) -> Self { fn from_client(client: redis::Client, worker_threads: usize) -> Self {
todo!() let (tx, rx) = sync::mpsc::unbounded_channel::<SlugDbMessage>();
// I want a FILO queue with a spin lock for consumption.
// I'm not sure this is the best way to implement this.
// (Alternatively: is there a better architecture?)
let rx = Arc::new(sync::Mutex::new(rx));
for _ in 0..worker_threads {
let mut connection = client.get_connection().expect("Could not open connection to Redis server.");
clone_to_move!(rx);
tokio::spawn(async move {
while let Some(msg) = {(*rx.lock().await).recv().await} {
match msg {
SlugDbMessage::Add(slug, url) => {
todo!()
},
}
}
});
}
SlugDatabase {
tx,
}
} }
fn insert_slug(&self, slug: Slug, url: Url) -> Result<(), ()> { fn insert_slug(&self, slug: Slug, url: Url) -> Result<(), ()> {
@ -128,7 +163,7 @@ struct SlugFactory {
slug_chars: BTreeSet<char>, slug_chars: BTreeSet<char>,
} }
#[derive(Debug)] #[derive(Clone, Debug)]
struct Slug(String); struct Slug(String);
enum InvalidSlug { enum InvalidSlug {
@ -199,7 +234,7 @@ async fn serve() {
let db = { let db = {
let client = redis::Client::open(config.db.address).expect("Error opening Redis database."); let client = redis::Client::open(config.db.address).expect("Error opening Redis database.");
//let conn = Connection::open(config.db_location).expect("Could not open database."); //let conn = Connection::open(config.db_location).expect("Could not open database.");
Arc::new(SlugDatabase::from_client(client)) Arc::new(SlugDatabase::from_client(client, config.db.worker_threads))
}; };
// GET / // GET /