Skip to content

Commit

Permalink
feat: extract next runtime into separate binary (#679)
Browse files Browse the repository at this point in the history
* feat: extract next runtime into separate binary

* fix: remove startrequestsservice name
  • Loading branch information
oddgrd authored Mar 6, 2023
1 parent 69b82e6 commit 52096fc
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 102 deletions.
1 change: 0 additions & 1 deletion cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,6 @@ impl Shuttle {

let start_request = StartRequest {
deployment_id: id.as_bytes().to_vec(),
service_name,
ip: addr.to_string(),
};

Expand Down
8 changes: 1 addition & 7 deletions deployer/src/deployment/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ impl Built {
.unwrap();
run(
self.id,
self.service_name,
runtime_client,
address,
deployment_updater,
Expand Down Expand Up @@ -280,7 +279,6 @@ async fn load(
#[instrument(skip(runtime_client, deployment_updater, kill_recv, cleanup), fields(state = %State::Running))]
async fn run(
id: Uuid,
service_name: String,
runtime_client: &mut RuntimeClient<Channel>,
address: SocketAddr,
deployment_updater: impl DeploymentUpdater,
Expand All @@ -294,7 +292,6 @@ async fn run(

let start_request = tonic::Request::new(StartRequest {
deployment_id: id.as_bytes().to_vec(),
service_name: service_name.clone(),
ip: address.to_string(),
});

Expand All @@ -310,10 +307,7 @@ async fn run(

while let Ok(kill_id) = kill_recv.recv().await {
if kill_id == id {
let stop_request = tonic::Request::new(StopRequest {
deployment_id: id.as_bytes().to_vec(),
service_name: service_name.clone(),
});
let stop_request = tonic::Request::new(StopRequest {});
response = runtime_client.stop(stop_request).await;

break;
Expand Down
6 changes: 5 additions & 1 deletion runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ publish = false
[[bin]]
name = "rocket"

[[bin]]
name = "next"

[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
Expand All @@ -23,6 +26,7 @@ tonic = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
uuid = { workspace = true, features = ["v4"] }
# TODO: bump these crates to 6.0 when we bump rust to >= 1.66
wasi-common = "4.0.0"
wasmtime = "4.0.0"
wasmtime-wasi = "4.0.0"
Expand All @@ -35,7 +39,7 @@ rocket = "0.5.0-rc.2"

[dependencies.shuttle-common]
workspace = true
features = ["wasm"]
features = ["wasm", "service"]

[dependencies.shuttle-proto]
workspace = true
Expand Down
4 changes: 2 additions & 2 deletions runtime/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
all: axum

axum:
cd ../tmp/axum-wasm-expanded; cargo build --target wasm32-wasi
cp ../tmp/axum-wasm-expanded/target/wasm32-wasi/debug/shuttle_axum_expanded.wasm axum.wasm
cd tests/resources/axum-wasm-expanded; cargo build --target wasm32-wasi
cp tests/resources/axum-wasm-expanded/target/wasm32-wasi/debug/shuttle_axum_expanded.wasm axum.wasm

test: axum
cargo test --all-features -- --nocapture
Expand Down
21 changes: 12 additions & 9 deletions runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ make test
Load and run:

```bash
cargo run -- --axum --provisioner-address http://localhost:5000
cargo run --bin next -- --port 6001
```

In another terminal:
Expand All @@ -40,24 +40,27 @@ In another terminal:
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"service_name": "Tonic", "path": "/home/<path to shuttle>/runtime/axum.wasm"}' localhost:6001 runtime.Runtime/Load

# start
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"service_name": "Tonic", "deployment_id": "MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw"}' localhost:6001 runtime.Runtime/Start
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"deployment_id": "MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw", "ip": "127.0.0.1:8000"}' localhost:6001 runtime.Runtime/Start

# subscribe to logs (unimplemented)
# subscribe to logs
grpcurl -plaintext -import-path ../proto -proto runtime.proto localhost:6001 runtime.Runtime/SubscribeLogs

# stop
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"service_name": "Tonic", "deployment_id": "MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw"}' localhost:6001 runtime.Runtime/Stop
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{}' localhost:6001 runtime.Runtime/Stop
```

Curl the service:
```bash
curl localhost:7002/hello
curl localhost:8000/hello

curl localhost:7002/goodbye
curl localhost:8000/goodbye
```

## shuttle-legacy
This will no loger load a `.so` will the code to start the runtime will be codegened for all services.

This will no longer load a `.so` file, the code to start the runtime will be
codegened for all services.

An example can be found in `src/bin/rocket.rs` which contains the secrets rocket example at the bottom and the codegen at the top.

To test, first start a provisioner from the root directory using:
Expand All @@ -69,7 +72,7 @@ docker-compose -f docker-compose.rendered.yml up provisioner
Then in another shell, start the wrapped runtime using the clap CLI:

```bash
cargo run -- --port 6001 --storage-manager-type working-dir --storage-manager-path ./
cargo run --bin rocket -- --port 6001 --storage-manager-type working-dir --storage-manager-path ./
```

Or directly (this is the path hardcoded in `deployer::start`):
Expand All @@ -87,7 +90,7 @@ Then in another shell, load the service and start it up:
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"service_name": "Tonic", "path": "/home/<path to shuttle>/examples/rocket/hello-world/target/debug/libhello_world.so", "secrets": {"MY_API_KEY": "test"}}' localhost:6001 runtime.Runtime/Load

# run (this deployment id is default uuid encoded as base64)
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"service_name": "Tonic", "deployment_id": "MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw", "ip": "127.0.0.1:8000"}' localhost:6001 runtime.Runtime/Start
grpcurl -plaintext -import-path ../proto -proto runtime.proto -d '{"deployment_id": "MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAw", "ip": "127.0.0.1:8000"}' localhost:6001 runtime.Runtime/Start

# subscribe to logs
grpcurl -plaintext -import-path ../proto -proto runtime.proto localhost:6001 runtime.Runtime/SubscribeLogs
Expand Down
40 changes: 40 additions & 0 deletions runtime/src/bin/next.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::{
net::{Ipv4Addr, SocketAddr},
time::Duration,
};

use clap::Parser;
use shuttle_proto::runtime::runtime_server::RuntimeServer;
use shuttle_runtime::{AxumWasm, NextArgs};
use tonic::transport::Server;
use tracing::trace;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};

#[tokio::main(flavor = "multi_thread")]
async fn main() {
let args = NextArgs::parse();

// TODO: replace with tracing helper from main branch
let fmt_layer = fmt::layer();
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();

tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.init();

trace!(args = ?args, "parsed args");

let addr = SocketAddr::new(Ipv4Addr::LOCALHOST.into(), args.port);

let mut server_builder =
Server::builder().http2_keepalive_interval(Some(Duration::from_secs(60)));

let axum = AxumWasm::default();
let svc = RuntimeServer::new(axum);
let router = server_builder.add_service(svc);

router.serve(addr).await.unwrap();
}
8 changes: 0 additions & 8 deletions runtime/src/args.rs → runtime/src/legacy/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ pub struct Args {
#[arg(long, default_value = "http://localhost:5000")]
pub provisioner_address: Endpoint,

/// Is this runtime for a legacy service
#[arg(long, conflicts_with("axum"))]
pub legacy: bool,

/// Is this runtime for an axum-wasm service
#[arg(long, conflicts_with("legacy"))]
pub axum: bool,

/// Type of storage manager to start
#[arg(long, value_enum)]
pub storage_manager_type: StorageManagerType,
Expand Down
6 changes: 5 additions & 1 deletion runtime/src/legacy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ use tonic::{
use tracing::{error, instrument, trace};
use uuid::Uuid;

use crate::{provisioner_factory::ProvisionerFactory, Args};
use crate::provisioner_factory::ProvisionerFactory;

use self::args::Args;

mod args;

pub async fn start(
loader: impl Loader<ProvisionerFactory<WorkingDirStorageManager>> + Send + 'static,
Expand Down
7 changes: 3 additions & 4 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
mod args;
mod axum;
mod legacy;
mod next;
mod provisioner_factory;

pub use args::{Args, StorageManagerType};
pub use axum::AxumWasm;
pub use legacy::{start, Legacy};
pub use next::AxumWasm;
pub use next::NextArgs;
pub use provisioner_factory::ProvisionerFactory;
66 changes: 0 additions & 66 deletions runtime/src/main.rs

This file was deleted.

9 changes: 9 additions & 0 deletions runtime/src/next/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use clap::Parser;

#[derive(Parser, Debug)]
#[command(version)]
pub struct NextArgs {
/// Port to start runtime on
#[arg(long)]
pub port: u16,
}
8 changes: 5 additions & 3 deletions runtime/src/axum/mod.rs → runtime/src/next/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ use wasmtime::{Engine, Linker, Module, Store};
use wasmtime_wasi::sync::net::UnixStream as WasiUnixStream;
use wasmtime_wasi::{WasiCtx, WasiCtxBuilder};

mod args;

pub use self::args::NextArgs;

extern crate rmp_serde as rmps;

const LOGS_FD: u32 = 20;
Expand Down Expand Up @@ -94,9 +98,7 @@ impl Runtime for AxumWasm {
&self,
request: tonic::Request<StartRequest>,
) -> Result<tonic::Response<StartResponse>, Status> {
let StartRequest {
deployment_id, ip, ..
} = request.into_inner();
let StartRequest { deployment_id, ip } = request.into_inner();

let address = SocketAddr::from_str(&ip)
.context("invalid socket address")
Expand Down

0 comments on commit 52096fc

Please sign in to comment.