Skip to content

Commit

Permalink
Merge pull request #29 from Overmuse/SR/retry_errors
Browse files Browse the repository at this point in the history
retry sending requests with backoff on errors
  • Loading branch information
SebRollen authored Jul 14, 2021
2 parents 265e263 + f52ee9d commit 23b69c2
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 5 deletions.
78 changes: 77 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[package]
name = "trader"
version = "1.1.0"
version = "1.1.1"
authors = ["RollenRegistratorBot <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
again = "0.1.2"
alpaca = { git = "ssh://[email protected]/Overmuse/alpaca", tag = "v0.7.0" }
anyhow = "1.0.40"
config = "0.11.0"
Expand Down
76 changes: 73 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ fn parse_message(msg: OwnedMessage) -> Result<OrderIntent> {
}

#[tracing::instrument(name = "Executing OrderIntent", skip(api, oi))]
async fn execute_order(api: &Client, oi: OrderIntent) -> Result<Order> {
async fn execute_order(api: &Client, oi: &OrderIntent) -> Result<Order> {
info!("Submitting order intent: {:?}", &oi);
api.send(SubmitOrder(oi)).await.map_err(From::from)
api.send(SubmitOrder(oi.clone())).await.map_err(From::from)
}

#[tracing::instrument(name = "Received message", skip(api, msg))]
async fn handle_message(api: &Client, msg: OwnedMessage) -> Result<Order> {
let order_intent = parse_message(msg)?;
execute_order(api, order_intent).await
again::retry(|| execute_order(api, &order_intent)).await
}

pub async fn run(settings: Settings) -> Result<()> {
Expand Down Expand Up @@ -195,4 +195,74 @@ mod test {

handle_message(&client, msg).await.unwrap();
}

#[tokio::test]
async fn handles_trainsient_errors() {
let payload = r#"{"symbol":"AAPL","qty":"1.5","side":"buy","type":"limit","limit_price":"100","time_in_force":"gtc","extended_hours":false,"client_order_id":"TEST","order_class":"simple"}"#;
let msg = OwnedMessage::new(
Some(payload.as_bytes().to_vec()), // payload
None, // header
"test".into(), // topic
Timestamp::NotAvailable, //timestamp
1, // partition
0, // offset
None, // headers
);

let m1 = mock("POST", "/orders")
.match_header("apca-api-key-id", "APCA_API_KEY_ID")
.match_header("apca-api-secret-key", "APCA_API_SECRET_KEY")
.match_body(payload)
.with_status(500)
.create();
let m2 = mock("POST", "/orders")
.match_header("apca-api-key-id", "APCA_API_KEY_ID")
.match_header("apca-api-secret-key", "APCA_API_SECRET_KEY")
.match_body(payload)
.with_body(
r#"{
"id": "904837e3-3b76-47ec-b432-046db621571b",
"client_order_id": "TEST",
"created_at": "2018-10-05T05:48:59Z",
"updated_at": "2018-10-05T05:48:59Z",
"submitted_at": "2018-10-05T05:48:59Z",
"filled_at": null,
"expired_at": null,
"canceled_at": null,
"failed_at": null,
"replaced_at": null,
"replaced_by": null,
"replaces": null,
"asset_id": "904837e3-3b76-47ec-b432-046db621571b",
"symbol": "AAPL",
"asset_class": "us_equity",
"notional": null,
"qty": "1.5",
"filled_qty": "0",
"filled_avg_price": null,
"type": "limit",
"side": "buy",
"time_in_force": "gtc",
"limit_price": "100.00",
"status": "new",
"extended_hours": false,
"legs": null,
"trail_price": null,
"trail_percent": null,
"hwm": null
}"#,
)
.create();

let client = Client::new(
mockito::server_url(),
"APCA_API_KEY_ID".to_string(),
"APCA_API_SECRET_KEY".to_string(),
)
.unwrap();

handle_message(&client, msg).await.unwrap();
m1.assert();
m2.assert();
}
}

0 comments on commit 23b69c2

Please sign in to comment.