-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathmain.rs
79 lines (70 loc) · 4.41 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
use std::fs::File;
use std::io::Read;
use std::net::SocketAddr;
use axum::routing::get_service;
use axum::Router;
use perspective::client::{TableInitOptions, UpdateData};
use perspective::server::Server;
use tower_http::services::{ServeDir, ServeFile};
use tower_http::trace::TraceLayer;
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::fmt::layer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::registry;
const ROOT_PATH: &str = "../..";
const ARROW_FILE_PATH: &str = "node_modules/superstore-arrow/superstore.arrow";
const SERVER_ADDRESS: &str = "0.0.0.0:3000";
/// A local error synonym for this module only.
type AppError = Box<dyn std::error::Error + Send + Sync>;
/// Load the example Apache Arrow file from disk and create a
/// [`perspective::Table`] named "my_data_source".
async fn load_server_arrow(server: &Server) -> Result<(), AppError> {
let client = server.new_local_client();
let mut file = File::open(std::path::Path::new(ROOT_PATH).join(ARROW_FILE_PATH))?;
let mut feather = Vec::with_capacity(file.metadata()?.len() as usize);
file.read_to_end(&mut feather)?;
let data = UpdateData::Arrow(feather.into());
let mut options = TableInitOptions::default();
options.set_name("my_data_source");
client.table(data.into(), options).await?;
client.close().await;
Ok(())
}
/// Host a combination HTTP file server + WebSocket server, which serves a
/// simple Perspective application. The app's HTML, etc., assets are served
/// from the root, while the app's embedded WebAssembly [`perspective::Client`]
/// will connect to this server over a WebSocket via the path `/ws`.
async fn start_web_server_and_block(server: Server) -> Result<(), AppError> {
let app = Router::new()
.route("/", get_service(ServeFile::new("src/index.html")))
.route("/ws", perspective::axum::websocket_handler())
.fallback_service(ServeDir::new(ROOT_PATH))
.with_state(server)
.layer(TraceLayer::new_for_http());
let service = app.into_make_service_with_connect_info::<SocketAddr>();
let listener = tokio::net::TcpListener::bind(SERVER_ADDRESS).await?;
tracing::info!("listening on {}", listener.local_addr()?);
axum::serve(listener, service).await?;
Ok(())
}
#[tokio::main(flavor = "multi_thread")]
async fn main() -> Result<(), AppError> {
registry()
.with(layer().compact().with_filter(LevelFilter::INFO))
.init();
let server = Server::default();
load_server_arrow(&server).await?;
start_web_server_and_block(server).await?;
Ok(())
}