Skip to content

Commit

Permalink
Add server skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
reinterpretcat committed Aug 25, 2020
1 parent b918901 commit bbfa3fd
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 18 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
members = [
"common",
"lambdas",
"server",
"solver",
]

Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@ another Rust project which implements a rich VRP solver functionality, you can f

# Overview

## Architecture
This repo contains two implementations of REST API:

* `server` a traditional server approach built using [actix-web framework](https://github.com/actix/actix-web)
* `serverless` a serverless approach using AWS lambdas

## Server approach


## Serverless approach

### Architecture

On API level, there are two public endpoints:

Expand Down Expand Up @@ -42,7 +52,8 @@ so another logic might be needed here and it is better to avoid coupling problem

- __Rust code__:
- `./common`: contains shared code used by different crates in the project
- `./lambdas`: contains code for AWS lambda functions
- `./lambdas`: contains code for AWS lambda functions used by `serverless` approach
- `./server`: contains code for server approach
- `./solver`: contains a binary crate for solving VRP problem
- __Build & Deployment & Test__
- `./terraform`: terraform configuration to deploy AWS resources
Expand Down Expand Up @@ -109,7 +120,7 @@ It builds rust code and copies build artifacts into `artifacts` folder.
terraform apply -var-file="private.tfvars"
```

## Test
## Test serverless

If you decided to use different AWS region, adjust url in tests scripts according to
[AWS documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-call-api.html).
Expand Down
2 changes: 1 addition & 1 deletion lambdas/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2018"

[dependencies]
common = { path = "../common" }
vrp-pragmatic = "1.2.4"
vrp-pragmatic = "1.4.2"

lambda_runtime = "0.2.1"
aws_lambda_events="0.3.0"
Expand Down
34 changes: 20 additions & 14 deletions lambdas/src/gateway/poll/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use common::aws::download_from_s3;
use common::models::{AppError, Context, Progress};
use common::runtime::{get_async_runtime, get_solution_key, get_state};
use lambda_runtime::{error::HandlerError, lambda};
use lambdas::common::{conflict, internal_server_error, no_content, not_found, ok, bad_request};
use lambdas::common::{bad_request, conflict, internal_server_error, no_content, not_found, ok};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
Expand All @@ -25,26 +25,32 @@ fn get_solution_response(
let submit_id = request.query_string_parameters.get("submit_id").cloned();

if submit_id.is_none() {
return Ok(bad_request(Some("no submit_id specified in query string parameters".to_string())))
return Ok(bad_request(Some(
"no submit_id specified in query string parameters".to_string(),
)));
}

let ctx = Context::new(submit_id.expect("invalid submit id"))?;

get_async_runtime()?.block_on(async move {
let state = get_state(&ctx).await;

Ok(match state.as_ref().ok().and_then(|state| state.progress()) {
Some(progress) if is_not_yet_solved(progress.clone()) => {
// TODO based on progress and algorithm termination settings, we can provide more
// information about when to expect solution to be ready
no_content(None)
}
Some(progress) if progress == Progress::Success => ok(Some(get_solution(&ctx).await?)),
Some(progress) if progress == Progress::Failed => {
conflict(state.ok().and_then(|s| s.payload()))
}
_ => not_found(None),
})
Ok(
match state.as_ref().ok().and_then(|state| state.progress()) {
Some(progress) if is_not_yet_solved(progress.clone()) => {
// TODO based on progress and algorithm termination settings, we can provide more
// information about when to expect solution to be ready
no_content(None)
}
Some(progress) if progress == Progress::Success => {
ok(Some(get_solution(&ctx).await?))
}
Some(progress) if progress == Progress::Failed => {
conflict(state.ok().and_then(|s| s.payload()))
}
_ => not_found(None),
},
)
})
}

Expand Down
12 changes: 12 additions & 0 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "server"
version = "0.1.0"
authors = ["reinterpretcat <ilya.builuk@gmail.com>"]
edition = "2018"


[dependencies]
common = { path = "../common" }
vrp-pragmatic = "1.4.2"

actix-web = "3.0.0-beta.3"
14 changes: 14 additions & 0 deletions server/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use actix_web::{get, web, App, HttpServer, Responder};

#[get("/{id}/{name}/index.html")]
async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder {
format!("Hello {}! id:{}", name, id)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().service(index))
.bind("127.0.0.1:8080")?
.run()
.await
}

0 comments on commit bbfa3fd

Please sign in to comment.