Better error handling in create_transaction
This commit is contained in:
parent
a5e3b402fa
commit
dcc3590ac3
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -110,6 +110,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"cbindgen",
|
"cbindgen",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"http-api-problem",
|
||||||
"log",
|
"log",
|
||||||
"mockito",
|
"mockito",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -476,6 +477,17 @@ dependencies = [
|
|||||||
"itoa",
|
"itoa",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-api-problem"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4760c8ea7ae413a5e4d122c83beb37ae0baf9b978af55dc8a161b7fd5fcd6458"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http-body"
|
name = "http-body"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -13,6 +13,7 @@ cbindgen = "0.14.4"
|
|||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
|
http-api-problem = "0.17"
|
||||||
mockito = "0.26.0"
|
mockito = "0.26.0"
|
||||||
reqwest = { version = "0.10", features = ["blocking", "json", "gzip"] }
|
reqwest = { version = "0.10", features = ["blocking", "json", "gzip"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -5,9 +5,6 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
template<typename T = void>
|
|
||||||
struct Option;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct FFIResult {
|
struct FFIResult {
|
||||||
enum class Tag : uint8_t {
|
enum class Tag : uint8_t {
|
||||||
@ -99,7 +96,7 @@ struct RawShop {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RawTransaction {
|
struct RawTransaction {
|
||||||
Option<uint32_t> id;
|
uint32_t id;
|
||||||
uint32_t shop_id;
|
uint32_t shop_id;
|
||||||
const char *mod_name;
|
const char *mod_name;
|
||||||
uint32_t local_form_id;
|
uint32_t local_form_id;
|
||||||
@ -139,6 +136,7 @@ struct _Helper_0 {
|
|||||||
FFIResult<RawShopVec> _raw_shop_vec_result;
|
FFIResult<RawShopVec> _raw_shop_vec_result;
|
||||||
FFIResult<RawInteriorRefVec> _raw_interior_ref_vec_result;
|
FFIResult<RawInteriorRefVec> _raw_interior_ref_vec_result;
|
||||||
FFIResult<RawMerchandiseVec> _raw_merchandise_vec_result;
|
FFIResult<RawMerchandiseVec> _raw_merchandise_vec_result;
|
||||||
|
FFIResult<RawTransaction> _raw_transaction_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// dummy extern C block to close curly brace (did I mention this is a bad hack?)
|
// dummy extern C block to close curly brace (did I mention this is a bad hack?)
|
||||||
|
@ -77,6 +77,7 @@ struct _Helper_0 {
|
|||||||
FFIResult<RawShopVec> _raw_shop_vec_result;
|
FFIResult<RawShopVec> _raw_shop_vec_result;
|
||||||
FFIResult<RawInteriorRefVec> _raw_interior_ref_vec_result;
|
FFIResult<RawInteriorRefVec> _raw_interior_ref_vec_result;
|
||||||
FFIResult<RawMerchandiseVec> _raw_merchandise_vec_result;
|
FFIResult<RawMerchandiseVec> _raw_merchandise_vec_result;
|
||||||
|
FFIResult<RawTransaction> _raw_transaction_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
// dummy extern C block to close curly brace (did I mention this is a bad hack?)
|
// dummy extern C block to close curly brace (did I mention this is a bad hack?)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::{convert::TryFrom, ffi::CStr, ffi::CString, os::raw::c_char, slice};
|
use std::{convert::TryFrom, ffi::CStr, ffi::CString, os::raw::c_char, slice, str};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use http_api_problem::HttpApiProblem;
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -61,7 +62,10 @@ impl Transaction {
|
|||||||
impl From<RawTransaction> for Transaction {
|
impl From<RawTransaction> for Transaction {
|
||||||
fn from(raw_transaction: RawTransaction) -> Self {
|
fn from(raw_transaction: RawTransaction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: raw_transaction.id,
|
id: match raw_transaction.id {
|
||||||
|
0 => None,
|
||||||
|
_ => Some(raw_transaction.id),
|
||||||
|
},
|
||||||
shop_id: raw_transaction.shop_id,
|
shop_id: raw_transaction.shop_id,
|
||||||
mod_name: unsafe { CStr::from_ptr(raw_transaction.mod_name) }
|
mod_name: unsafe { CStr::from_ptr(raw_transaction.mod_name) }
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
@ -83,7 +87,7 @@ impl From<RawTransaction> for Transaction {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct RawTransaction {
|
pub struct RawTransaction {
|
||||||
pub id: Option<u32>,
|
pub id: u32,
|
||||||
pub shop_id: u32,
|
pub shop_id: u32,
|
||||||
pub mod_name: *const c_char,
|
pub mod_name: *const c_char,
|
||||||
pub local_form_id: u32,
|
pub local_form_id: u32,
|
||||||
@ -99,7 +103,7 @@ pub struct RawTransaction {
|
|||||||
impl From<Transaction> for RawTransaction {
|
impl From<Transaction> for RawTransaction {
|
||||||
fn from(transaction: Transaction) -> Self {
|
fn from(transaction: Transaction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: transaction.id,
|
id: transaction.id.unwrap_or(0),
|
||||||
shop_id: transaction.shop_id,
|
shop_id: transaction.shop_id,
|
||||||
mod_name: CString::new(transaction.mod_name)
|
mod_name: CString::new(transaction.mod_name)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
@ -153,15 +157,34 @@ pub extern "C" fn create_transaction(
|
|||||||
.json(&transaction)
|
.json(&transaction)
|
||||||
.send()?;
|
.send()?;
|
||||||
info!("create transaction response from api: {:?}", &resp);
|
info!("create transaction response from api: {:?}", &resp);
|
||||||
|
let status = resp.status();
|
||||||
let bytes = resp.bytes()?;
|
let bytes = resp.bytes()?;
|
||||||
let json: Transaction = serde_json::from_slice(&bytes)?;
|
if status.is_success() {
|
||||||
if let Some(id) = json.id {
|
let json: Transaction = serde_json::from_slice(&bytes)?;
|
||||||
update_file_cache(
|
if let Some(id) = json.id {
|
||||||
&file_cache_dir(api_url)?.join(format!("transaction_{}.json", id)),
|
update_file_cache(
|
||||||
&bytes,
|
&file_cache_dir(api_url)?.join(format!("transaction_{}.json", id)),
|
||||||
)?;
|
&bytes,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(json)
|
||||||
|
} else {
|
||||||
|
match serde_json::from_slice::<HttpApiProblem>(&bytes) {
|
||||||
|
Ok(api_problem) => {
|
||||||
|
let detail = api_problem.detail.unwrap_or("".to_string());
|
||||||
|
error!("Server {} error: {}. {}", status, api_problem.title, detail);
|
||||||
|
Err(anyhow!(format!(
|
||||||
|
"Server {} error: {}. {}",
|
||||||
|
status, api_problem.title, detail
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
let detail = str::from_utf8(&bytes).unwrap_or("unknown");
|
||||||
|
error!("Server {} error: {}", status, detail);
|
||||||
|
Err(anyhow!(format!("Server {} error: {}", status, detail)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match inner(&api_url, &api_key, transaction) {
|
match inner(&api_url, &api_key, transaction) {
|
||||||
@ -226,7 +249,7 @@ mod tests {
|
|||||||
let mod_name = CString::new("Skyrim.esm").unwrap().into_raw();
|
let mod_name = CString::new("Skyrim.esm").unwrap().into_raw();
|
||||||
let name = CString::new("Item").unwrap().into_raw();
|
let name = CString::new("Item").unwrap().into_raw();
|
||||||
let raw_transaction = RawTransaction {
|
let raw_transaction = RawTransaction {
|
||||||
id: None,
|
id: 0,
|
||||||
shop_id: 1,
|
shop_id: 1,
|
||||||
mod_name,
|
mod_name,
|
||||||
local_form_id: 1,
|
local_form_id: 1,
|
||||||
@ -242,7 +265,7 @@ mod tests {
|
|||||||
mock.assert();
|
mock.assert();
|
||||||
match result {
|
match result {
|
||||||
FFIResult::Ok(raw_transaction) => {
|
FFIResult::Ok(raw_transaction) => {
|
||||||
assert_eq!(raw_transaction.id, Some(1));
|
assert_eq!(raw_transaction.id, 1);
|
||||||
assert_eq!(raw_transaction.shop_id, 1);
|
assert_eq!(raw_transaction.shop_id, 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
unsafe { CStr::from_ptr(raw_transaction.mod_name).to_string_lossy() },
|
unsafe { CStr::from_ptr(raw_transaction.mod_name).to_string_lossy() },
|
||||||
@ -278,7 +301,7 @@ mod tests {
|
|||||||
let mod_name = CString::new("Skyrim.esm").unwrap().into_raw();
|
let mod_name = CString::new("Skyrim.esm").unwrap().into_raw();
|
||||||
let name = CString::new("Item").unwrap().into_raw();
|
let name = CString::new("Item").unwrap().into_raw();
|
||||||
let raw_transaction = RawTransaction {
|
let raw_transaction = RawTransaction {
|
||||||
id: None,
|
id: 0,
|
||||||
shop_id: 1,
|
shop_id: 1,
|
||||||
mod_name,
|
mod_name,
|
||||||
local_form_id: 1,
|
local_form_id: 1,
|
||||||
|
Loading…
Reference in New Issue
Block a user