chore: initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
target/
|
||||||
|
|
||||||
|
.history/
|
||||||
2914
Cargo.lock
generated
Normal file
2914
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["application", "backend", "frontend"]
|
||||||
|
resolver = "3"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
axum = "0.8.8"
|
||||||
|
futures = "0.3.32"
|
||||||
|
tokio = "1.49.0"
|
||||||
|
tracing = "0.1.44"
|
||||||
0
Dockerfile
Normal file
0
Dockerfile
Normal file
13
application/Cargo.toml
Normal file
13
application/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "application"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
frontend = { path = "../frontend" }
|
||||||
|
backend = { path = "../backend" }
|
||||||
|
|
||||||
|
axum = { workspace = true, features = ["tokio", "ws"] }
|
||||||
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||||
|
clap = { version = "4.5.58", features = ["derive", "env"] }
|
||||||
|
tracing-subscriber = "0.3.22"
|
||||||
|
tracing = "0.1.44"
|
||||||
15
application/src/main.rs
Normal file
15
application/src/main.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
struct Args {}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let args = Parser::parse();
|
||||||
|
let Args {} = args;
|
||||||
|
|
||||||
|
let hello = backend::hi();
|
||||||
|
let world = frontend::world();
|
||||||
|
|
||||||
|
println!("{hello} {world}!");
|
||||||
|
}
|
||||||
14
backend/Cargo.toml
Normal file
14
backend/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "backend"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = { workspace = true, features = ["tokio", "ws"] }
|
||||||
|
axum-extra = { version = "0.12.5", features = ["typed-routing"] }
|
||||||
|
futures = { workspace = true }
|
||||||
|
postage = { version = "0.5.0", default-features = false, features = [
|
||||||
|
"futures-traits",
|
||||||
|
] }
|
||||||
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
tokio = { workspace = true, features = ["rt"] }
|
||||||
|
tracing = { workspace = true }
|
||||||
75
backend/src/lib.rs
Normal file
75
backend/src/lib.rs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
use std::num::NonZero;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Router,
|
||||||
|
extract::{State, WebSocketUpgrade, ws::WebSocket},
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use axum_extra::routing::{RouterExt, TypedPath};
|
||||||
|
use futures::{SinkExt, Stream, StreamExt};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tokio::{runtime::Handle, task::LocalSet};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct AppState {
|
||||||
|
websocket_tx: postage::dispatch::Sender<WebSocket>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, TypedPath)]
|
||||||
|
#[typed_path("/ws")]
|
||||||
|
struct Ws {}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
async fn get_ws(
|
||||||
|
Ws {}: Ws,
|
||||||
|
upgrade: WebSocketUpgrade,
|
||||||
|
State(app_state): State<AppState>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let mut websocket_tx = app_state.websocket_tx;
|
||||||
|
|
||||||
|
upgrade.on_upgrade(|websocket| async move {
|
||||||
|
websocket_tx.send(websocket).await.unwrap();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_rpc_server(mut websockets: impl Stream<Item = WebSocket> + Unpin) {
|
||||||
|
let local_set = LocalSet::new();
|
||||||
|
|
||||||
|
local_set
|
||||||
|
.run_until(async move {
|
||||||
|
while let Some(websocket) = websockets.next().await {
|
||||||
|
tracing::debug!(?websocket);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
local_set.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_router() -> Router<AppState> {
|
||||||
|
Router::new().typed_get(get_ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CreateAppArgs {
|
||||||
|
tokio_runtime_handle: Handle,
|
||||||
|
websocket_channel_capacity: NonZero<usize>,
|
||||||
|
rpc_workers: NonZero<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_app(
|
||||||
|
CreateAppArgs {
|
||||||
|
tokio_runtime_handle,
|
||||||
|
websocket_channel_capacity,
|
||||||
|
rpc_workers,
|
||||||
|
}: CreateAppArgs,
|
||||||
|
) -> Router<()> {
|
||||||
|
let (websocket_tx, websocket_rx) = postage::dispatch::channel(websocket_channel_capacity.get());
|
||||||
|
|
||||||
|
for _ in 0..=rpc_workers.get() {
|
||||||
|
let websocket_rx = websocket_rx.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = AppState { websocket_tx };
|
||||||
|
create_router().with_state(state)
|
||||||
|
}
|
||||||
6
frontend/Cargo.toml
Normal file
6
frontend/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "frontend"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
leptos = "0.8.15"
|
||||||
3
frontend/src/lib.rs
Normal file
3
frontend/src/lib.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub fn world() -> String {
|
||||||
|
"world".into()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user