Add multiple targets for server and agent, start implementing migrations

This commit is contained in:
R Tyler Croy 2023-01-28 15:05:05 -08:00
parent 0a3b14b942
commit 2789850f5b
No known key found for this signature in database
GPG Key ID: E5C92681BEF6CEA2
5 changed files with 158 additions and 7 deletions

View File

@ -3,7 +3,13 @@ name = "janky"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "janky-server"
path = "src/server/main.rs"
[[bin]]
name = "janky-agent"
path = "src/agent/main.rs"
[dependencies]
async-std = { version = "1", features = ["attributes"] }
@ -16,6 +22,6 @@ html-escape = "~0.2.6"
log = "~0.4.8"
pretty_env_logger = "~0.3.1"
serde_json = "~1.0.0"
sqlx = { version = "~0.5.1", features = ["chrono", "json", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
sqlx = { version = "~0.5.1", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
tide = "0"
uuid = { version = "~0.8.1", features = ["v4", "serde"]}

View File

@ -0,0 +1,10 @@
CREATE TABLE agents (
id SERIAL PRIMARY KEY,
uuid UUID NOT NULL UNIQUE,
name TEXT NOT NULL,
capabilities TEXT,
url TEXT NOT NUll,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE UNIQUE INDEX uuid_idx ON agents(uuid);

4
src/agent/main.rs Normal file
View File

@ -0,0 +1,4 @@
fn main() {
println!("Janky agent!");
todo!();
}

View File

@ -89,11 +89,12 @@ async fn main() -> Result<(), tide::Error> {
dotenv().ok();
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
let state = AppState::new(
SqlitePool::connect(&database_url)
.await
.expect("Failed to open SqlitePool"),
);
let pool = SqlitePool::connect(&database_url).await?;
if database_url == ":memory:" {
sqlx::migrate!().run(&pool).await?;
}
let state = AppState::new(pool);
state.register_templates().await;
let mut app = tide::with_state(state);

130
src/server/main.rs Normal file
View File

@ -0,0 +1,130 @@
/*
* This is the main Janky entrypoint for the server"
*/
#[macro_use]
extern crate serde_json;
use async_std::sync::{Arc, RwLock};
use dotenv::dotenv;
use handlebars::Handlebars;
use log::*;
use sqlx::SqlitePool;
#[derive(Clone, Debug)]
pub struct AppState<'a> {
pub db: SqlitePool,
hb: Arc<RwLock<Handlebars<'a>>>,
}
impl AppState<'_> {
fn new(db: SqlitePool) -> Self {
Self {
db: db,
hb: Arc::new(RwLock::new(Handlebars::new())),
}
}
pub async fn register_templates(&self) -> Result<(), handlebars::TemplateFileError> {
let mut hb = self.hb.write().await;
hb.clear_templates();
hb.register_templates_directory(".hbs", "views")
}
pub async fn render(
&self,
name: &str,
data: &serde_json::Value,
) -> Result<tide::Body, tide::Error> {
/*
* In debug mode, reload the templates on ever render to avoid
* needing a restart
*/
#[cfg(debug_assertions)]
{
self.register_templates().await;
}
let hb = self.hb.read().await;
let view = hb.render(name, data)?;
Ok(tide::Body::from_string(view))
}
}
/**
* The routes module contains all the tide routes and the logic to fulfill the responses for each
* route.
*
* Modules are nested for cleaner organization here
*/
mod routes {
use crate::AppState;
use log::*;
use std::collections::HashMap;
use tide::{Body, Request, StatusCode};
use uuid::Uuid;
/**
* GET /
*/
pub async fn index(req: Request<AppState<'_>>) -> Result<Body, tide::Error> {
let params = json!({
"page": "home"
});
let mut body = req.state().render("index", &params).await?;
body.set_mime("text/html");
Ok(body)
}
pub mod api {
use log::*;
use tide::{Body, Request, Response, StatusCode};
use crate::AppState;
}
}
#[async_std::main]
async fn main() -> Result<(), tide::Error> {
pretty_env_logger::init();
dotenv().ok();
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
let state = AppState::new(
SqlitePool::connect(&database_url)
.await
.expect("Failed to open SqlitePool"),
);
state.register_templates().await;
let mut app = tide::with_state(state);
#[cfg(not(debug_assertions))]
{
info!("Activating RELEASE mode configuration");
app.with(driftwood::ApacheCombinedLogger);
}
#[cfg(debug_assertions)]
{
info!("Activating DEBUG mode configuration");
info!("Enabling a very liberal CORS policy for debug purposes");
use tide::security::{CorsMiddleware, Origin};
let cors = CorsMiddleware::new()
.allow_methods(
"GET, POST, PUT, OPTIONS"
.parse::<tide::http::headers::HeaderValue>()
.unwrap(),
)
.allow_origin(Origin::from("*"))
.allow_credentials(false);
app.with(cors);
}
/*
* All builds will have apidocs, since they're handy
*/
app.at("/static").serve_dir("static/")?;
debug!("Configuring routes");
app.at("/").get(routes::index);
app.listen("0.0.0.0:8000").await?;
Ok(())
}