Skip to content

Commit

Permalink
feat: introduce dedicated server (#492)
Browse files Browse the repository at this point in the history
* feat: introduce dedicated server

* feat: introduce dedicated server

* feat: introduce dedicated server

* feat: introduce dedicated server

* feat: introduce dedicated server
  • Loading branch information
sundy-li authored Oct 25, 2024
1 parent d0d9510 commit 56ca4df
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 118 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ jobs:
sudo mv /tmp/cross /usr/local/bin/cross
- name: Build
shell: bash
env:
BUILD_FRONTEND: 1
run: |
make build-frontend
cross build --release --target=${{ matrix.target }} --bin=bendsql
- name: Publish Binary
uses: ./.github/actions/publish_binary
Expand Down Expand Up @@ -71,9 +70,8 @@ jobs:
targets: ${{ matrix.target }}
- name: Build
shell: bash
env:
BUILD_FRONTEND: 1
run: |
make build-frontend
cargo build --release --target=${{ matrix.target }} --bin=bendsql
- name: Publish Binary
uses: ./.github/actions/publish_binary
Expand Down
49 changes: 1 addition & 48 deletions cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{env, error::Error, process::Command};
use std::{env, error::Error};
use vergen::EmitBuilder;

fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -29,52 +29,5 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-env=BENDSQL_BUILD_INFO={}", info);
});

if env::var("BUILD_FRONTEND").is_ok() {
println!("cargo:warning=Start to build frontend dir via env BUILD_FRONTEND.");
let cwd = env::current_dir().expect("Failed to get current directory");
println!("cargo:warning=Current Dir {:?}.", cwd.display());

env::set_current_dir("../frontend").expect("Failed to change directory to ../frontend");
// Clean old frontend directory
let _ = Command::new("rm")
.arg("-rf")
.arg("../cli/frontend")
.status()
.expect("Failed to remove old frontend directory");

// Mkdir new dir
let _ = Command::new("mkdir")
.arg("-p")
.arg("../cli/frontend")
.status()
.expect("Failed to create frontend directory");

let _ = Command::new("yarn")
.arg("config")
.arg("set")
.arg("network-timeout")
.arg("600000")
.status()
.expect("Failed to set Yarn network timeout");

let _ = Command::new("yarn")
.arg("install")
.status()
.expect("Yarn install failed");

let _ = Command::new("yarn")
.arg("build")
.status()
.expect("Yarn build failed");

// 移动构建结果
let _ = Command::new("mv")
.arg("build")
.arg("../cli/frontend/")
.status()
.expect("Failed to move build directory");

env::set_current_dir(cwd).unwrap();
}
Ok(())
}
34 changes: 33 additions & 1 deletion cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub struct Config {
pub connection: ConnectionConfig,
#[serde(default)]
pub settings: SettingsConfig,
#[serde(default)]
pub server: ServerConfig,
}

#[derive(Clone, Debug, Deserialize, Default)]
Expand Down Expand Up @@ -99,6 +101,10 @@ pub struct Settings {
pub multi_line: bool,
/// whether replace '\n' with '\\n', default true.
pub replace_newline: bool,

pub bind_address: String,
pub bind_port: u16,
pub auto_open_browser: bool,
}

#[derive(ValueEnum, Clone, Debug, PartialEq, Deserialize)]
Expand Down Expand Up @@ -135,7 +141,9 @@ impl TryFrom<&str> for TimeOption {
}

impl Settings {
pub fn merge_config(&mut self, cfg: SettingsConfig) {
pub fn merge_config(&mut self, c: &Config) {
let cfg = c.settings.clone();

self.display_pretty_sql = cfg.display_pretty_sql.unwrap_or(self.display_pretty_sql);
self.prompt = cfg.prompt.unwrap_or_else(|| self.prompt.clone());
self.progress_color = cfg
Expand All @@ -152,6 +160,9 @@ impl Settings {
self.max_width = cfg.max_width.unwrap_or(self.max_width);
self.max_col_width = cfg.max_col_width.unwrap_or(self.max_col_width);
self.max_display_rows = cfg.max_display_rows.unwrap_or(self.max_display_rows);
self.auto_open_browser = c.server.auto_open_browser;
self.bind_address.clone_from(&c.server.bind_address);
self.bind_port = c.server.bind_port;
}

pub fn inject_ctrl_cmd(&mut self, cmd_name: &str, cmd_value: &str) -> Result<()> {
Expand Down Expand Up @@ -203,6 +214,14 @@ pub struct ConnectionConfig {
pub args: BTreeMap<String, String>,
}

#[derive(Clone, Debug, Deserialize)]
#[serde(default)]
pub struct ServerConfig {
pub bind_address: String,
pub bind_port: u16,
pub auto_open_browser: bool,
}

impl Config {
pub fn load() -> Self {
let paths = [
Expand Down Expand Up @@ -251,6 +270,9 @@ impl Default for Settings {
time: None,
multi_line: true,
replace_newline: true,
auto_open_browser: false,
bind_address: "127.0.0.1".to_string(),
bind_port: 8080,
}
}
}
Expand All @@ -267,3 +289,13 @@ impl Default for ConnectionConfig {
}
}
}

impl Default for ServerConfig {
fn default() -> Self {
Self {
bind_address: "127.0.0.1".to_string(),
bind_port: 8080,
auto_open_browser: true,
}
}
}
44 changes: 29 additions & 15 deletions cli/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;
use std::fmt::Write;
use std::{collections::HashSet, env};

use anyhow::{anyhow, Result};
use comfy_table::{Cell, CellAlignment, Table};
Expand All @@ -28,7 +28,7 @@ use crate::{
ast::{format_query, highlight_query},
config::{ExpandMode, OutputFormat, OutputQuoteStyle, Settings},
session::QueryKind,
web::start_server_and_open_browser,
web::set_data,
};

#[async_trait::async_trait]
Expand Down Expand Up @@ -98,6 +98,32 @@ impl<'a> FormatDisplay<'a> {
}
}

async fn display_graphical(&mut self, rows: &[Row]) -> Result<()> {
let mut result = String::new();
for row in rows {
result.push_str(&row.values()[0].to_string());
}

let perf_id = set_data(result);

let url = format!(
"http://{}:{}?perf_id={}",
self.settings.bind_address, self.settings.bind_port, perf_id
);

// Open the browser in a separate task if not in ssh mode
let in_sshmode = env::var("SSH_CLIENT").is_ok() || env::var("SSH_TTY").is_ok();
if !in_sshmode && self.settings.auto_open_browser {
if let Err(e) = webbrowser::open(&url) {
eprintln!("Failed to open browser: {}", e);
}
}

println!("View graphical online: \x1B[4m{}\x1B[0m", url);
println!();
Ok(())
}

async fn display_table(&mut self) -> Result<()> {
if self.settings.display_pretty_sql {
let format_sql = format_query(self.query);
Expand Down Expand Up @@ -142,19 +168,7 @@ impl<'a> FormatDisplay<'a> {
}

if self.kind == QueryKind::Graphical {
println!("Graphical query result: -- ");
let mut explain_results = Vec::new();
for result in &rows {
explain_results.push(result.values()[0].to_string());
}

tokio::spawn(async move {
if let Err(e) = start_server_and_open_browser(explain_results.join("")).await {
eprintln!("Failed to start server: {}", e);
}
});
println!();
return Ok(());
return self.display_graphical(&rows).await;
}

let schema = self.data.schema();
Expand Down
2 changes: 1 addition & 1 deletion cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ pub async fn main() -> Result<()> {
settings.output_format = OutputFormat::TSV;
}

settings.merge_config(config.settings);
settings.merge_config(&config);

if args.no_auto_complete {
settings.no_auto_complete = true;
Expand Down
31 changes: 29 additions & 2 deletions cli/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ use rustyline::history::DefaultHistory;
use rustyline::{CompletionType, Editor};
use tokio::fs::{remove_file, File};
use tokio::io::AsyncWriteExt;
use tokio::task::JoinHandle;
use tokio::time::Instant;
use tokio_stream::StreamExt;

use crate::config::Settings;
use crate::config::TimeOption;
use crate::display::{format_write_progress, ChunkDisplay, FormatDisplay};
use crate::helper::CliHelper;
use crate::web::find_available_port;
use crate::web::start_server;
use crate::VERSION;

static PROMPT_SQL: &str = "select name, 'f' as type from system.functions union all select name, 'd' as type from system.databases union all select name, 't' as type from system.tables union all select name, 'c' as type from system.columns limit 10000";
Expand Down Expand Up @@ -71,11 +74,12 @@ pub struct Session {
settings: Settings,
query: String,

server_handle: Option<JoinHandle<std::io::Result<()>>>,
keywords: Option<Arc<sled::Db>>,
}

impl Session {
pub async fn try_new(dsn: String, settings: Settings, is_repl: bool) -> Result<Self> {
pub async fn try_new(dsn: String, mut settings: Settings, is_repl: bool) -> Result<Self> {
let client = Client::new(dsn).with_name(format!("bendsql/{}", VERSION_SHORT.as_str()));
let conn = client.get_conn().await?;
let info = conn.info().await;
Expand Down Expand Up @@ -158,16 +162,31 @@ impl Session {
}
}
keywords = Some(Arc::new(db));
println!();
}

let server_handle = if is_repl {
let port = find_available_port(settings.bind_port).await;
let addr = settings.bind_address.clone();

let server_handle = tokio::spawn(async move { start_server(&addr, port).await });
println!("Started web server at {}:{}", settings.bind_address, port);
settings.bind_port = port;
Some(server_handle)
} else {
None
};

if is_repl {
println!();
}
Ok(Self {
client,
conn,
is_repl,
settings,
query: String::new(),
keywords,
server_handle,
})
}

Expand Down Expand Up @@ -692,3 +711,11 @@ fn replace_newline_in_box_display(query: &str) -> bool {
_ => true,
}
}

impl Drop for Session {
fn drop(&mut self) {
if let Some(handle) = self.server_handle.take() {
handle.abort();
}
}
}
Loading

0 comments on commit 56ca4df

Please sign in to comment.