Skip to content

Commit

Permalink
Merge pull request #2 from immanelg/cli
Browse files Browse the repository at this point in the history
CLI
  • Loading branch information
cospectrum authored Jan 3, 2024
2 parents 3cf7ae2 + 9a2dcda commit c55d8f2
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,6 @@ Cargo.lock

# !src
!memcrab
!memcrab-cli
!memcrab-cache
!memcrab-server
!memcrab-server
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"memcrab",
"memcrab-cache",
"memcrab-server",
"memcrab-cli"
]
exclude = ["examples"]

Expand Down
21 changes: 21 additions & 0 deletions memcrab-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "memcrab-cli"
version = "0.1.0"
edition = "2021"

description = """
Command line interface for Memcrab.
"""
license = "MIT OR Apache-2.0"
readme = "../README.md"
repository = "https://github.com/cospectrum/memcrab"

[dependencies]
anyhow = "1.0.79"
clap = { version = "4.4.12", features = ["derive"] }
memcrab = { version = "0.1.0", path = "../memcrab" }
memcrab-cache = { version = "0.1.0", path = "../memcrab-cache" }
memcrab-server = { version = "0.1.0", path = "../memcrab-server" }
rustyline = "13.0.0"
tokio = { version = "1.35.1", features = ["full"] }
tonic.workspace = true
24 changes: 24 additions & 0 deletions memcrab-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# memcrab-cli

Command line interface for memcrab

# Usage

Start a server
```bash
cargo run -- -H 127.0.0.1 -p 6969 -s &
```

Connect client to a running server
```bash
cargo run -- -H 127.0.0.1 -p 6969
```

This will start an interactive session. You can use `get` and `set` commands.

```
memcrab> set x 1 2 3
memcrab> get x
x: [1, 2, 3]
memcrab>
```
106 changes: 106 additions & 0 deletions memcrab-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use anyhow::bail;
use clap::Parser;
use core::num::NonZeroUsize;
use memcrab::RawClient;
use memcrab_cache::Cache;
use memcrab_server::start_grpc_server;
use rustyline::error::ReadlineError;
use rustyline::DefaultEditor;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(short = 'H', long, default_value = "127.0.0.1")]
host: String,

#[arg(short, long, default_value = "9090")]
port: String,

#[arg(short, long, action)]
server: bool,
}

async fn eval_lines(addr: String) -> anyhow::Result<()> {
let mut client = RawClient::connect(format!("http://{}", addr)).await?;
let mut editor = DefaultEditor::new()?;
loop {
let line = editor.readline("memcrab> ");
match line {
Ok(line) => {
eval_line(&mut client, line)
.await
.unwrap_or_else(|e| println!("error: {:?}", e));
}
Err(ReadlineError::Interrupted) => {
println!("Ctrl-c");
}
Err(ReadlineError::Eof) => {
println!("quit");
break;
}
Err(err) => {
println!("error: {:?}", err);
break;
}
}
}

Ok(())
}

async fn eval_line(client: &mut RawClient, line: String) -> anyhow::Result<()> {
let tokens = line.split_whitespace().collect::<Vec<_>>();
if tokens.is_empty() {
return Ok(());
}
if tokens[0] == "get" {
if tokens.len() != 2 {
bail!("syntax error: expected one key after `get`");
}
let resp = client.get(tokens[1]).await?;
match resp {
Some(val) => println!("{}: {:?}", tokens[1], val),
None => println!("no value set"),
}
} else if tokens[0] == "set" {
if tokens.len() < 3 {
bail!("syntax error: expected one key and bytes after `set`");
}

client
.set(
tokens[1],
tokens[2..]
.iter()
.map(|&s| s.parse().unwrap())
.collect::<Vec<u8>>(),
)
.await?;
} else {
bail!("syntax error: unexpected token {}", tokens[0]);
}
Ok(())
}

async fn serve(addr: String) -> anyhow::Result<()> {
let maxbytes = 100_000;
let maxlen = NonZeroUsize::new(110).unwrap();
let cache = Cache::new(maxlen, maxbytes);

start_grpc_server(addr.parse()?, cache).await.unwrap();
Ok(())
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();

let addr = format!("{}:{}", cli.host, cli.port);

if cli.server {
serve(addr).await?;
} else {
eval_lines(addr).await?;
}
Ok(())
}

0 comments on commit c55d8f2

Please sign in to comment.