perf: improve compression reliability and deployment safety
This commit is contained in:
@@ -46,7 +46,9 @@ struct PlansResponse {
|
||||
plans: Vec<PlanView>,
|
||||
}
|
||||
|
||||
async fn list_plans(State(state): State<AppState>) -> Result<Json<Envelope<PlansResponse>>, AppError> {
|
||||
async fn list_plans(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<Envelope<PlansResponse>>, AppError> {
|
||||
let plans = sqlx::query_as::<_, PlanView>(
|
||||
r#"
|
||||
SELECT
|
||||
@@ -422,7 +424,8 @@ async fn create_checkout(
|
||||
});
|
||||
|
||||
let mut idem_acquired = false;
|
||||
if let (Some(idem), Some(request_hash)) = (idempotency_key.as_deref(), request_hash.as_deref()) {
|
||||
if let (Some(idem), Some(request_hash)) = (idempotency_key.as_deref(), request_hash.as_deref())
|
||||
{
|
||||
match idempotency::begin(
|
||||
&state,
|
||||
idempotency::Scope::User(user_id),
|
||||
@@ -433,10 +436,14 @@ async fn create_checkout(
|
||||
.await?
|
||||
{
|
||||
idempotency::BeginResult::Replay { response_body, .. } => {
|
||||
let resp: CheckoutResponse = serde_json::from_value(response_body).map_err(|err| {
|
||||
AppError::new(ErrorCode::Internal, "幂等结果解析失败").with_source(err)
|
||||
})?;
|
||||
return Ok(Json(Envelope { success: true, data: resp }));
|
||||
let resp: CheckoutResponse =
|
||||
serde_json::from_value(response_body).map_err(|err| {
|
||||
AppError::new(ErrorCode::Internal, "幂等结果解析失败").with_source(err)
|
||||
})?;
|
||||
return Ok(Json(Envelope {
|
||||
success: true,
|
||||
data: resp,
|
||||
}));
|
||||
}
|
||||
idempotency::BeginResult::InProgress => {
|
||||
if let Some((_status, body)) = idempotency::wait_for_replay(
|
||||
@@ -451,14 +458,17 @@ async fn create_checkout(
|
||||
let resp: CheckoutResponse = serde_json::from_value(body).map_err(|err| {
|
||||
AppError::new(ErrorCode::Internal, "幂等结果解析失败").with_source(err)
|
||||
})?;
|
||||
return Ok(Json(Envelope { success: true, data: resp }));
|
||||
return Ok(Json(Envelope {
|
||||
success: true,
|
||||
data: resp,
|
||||
}));
|
||||
}
|
||||
return Err(AppError::new(
|
||||
ErrorCode::InvalidRequest,
|
||||
"请求正在处理中,请稍后重试",
|
||||
));
|
||||
}
|
||||
idempotency::BeginResult::Acquired { .. } => {
|
||||
idempotency::BeginResult::Acquired => {
|
||||
idem_acquired = true;
|
||||
}
|
||||
}
|
||||
@@ -525,8 +535,10 @@ async fn create_checkout(
|
||||
cus
|
||||
};
|
||||
|
||||
let success_url =
|
||||
format!("{}/dashboard/billing?checkout=success", state.config.public_base_url);
|
||||
let success_url = format!(
|
||||
"{}/dashboard/billing?checkout=success",
|
||||
state.config.public_base_url
|
||||
);
|
||||
let cancel_url = format!("{}/pricing?checkout=cancel", state.config.public_base_url);
|
||||
|
||||
stripe_create_checkout_session(
|
||||
@@ -619,7 +631,10 @@ async fn create_portal(
|
||||
.map_err(|err| AppError::new(ErrorCode::Internal, "查询用户失败").with_source(err))?;
|
||||
|
||||
let Some(customer_id) = customer_id.filter(|v| !v.trim().is_empty()) else {
|
||||
return Err(AppError::new(ErrorCode::InvalidRequest, "未找到 Stripe Customer"));
|
||||
return Err(AppError::new(
|
||||
ErrorCode::InvalidRequest,
|
||||
"未找到 Stripe Customer",
|
||||
));
|
||||
};
|
||||
|
||||
let return_url = format!("{}/dashboard/billing", state.config.public_base_url);
|
||||
@@ -631,7 +646,11 @@ async fn create_portal(
|
||||
}))
|
||||
}
|
||||
|
||||
async fn stripe_create_customer(secret: &str, email: &str, user_id: Uuid) -> Result<String, AppError> {
|
||||
async fn stripe_create_customer(
|
||||
secret: &str,
|
||||
email: &str,
|
||||
user_id: Uuid,
|
||||
) -> Result<String, AppError> {
|
||||
let resp: serde_json::Value = stripe_post_form(
|
||||
secret,
|
||||
"/v1/customers",
|
||||
@@ -723,10 +742,9 @@ async fn stripe_post_form(
|
||||
.map_err(|err| AppError::new(ErrorCode::Internal, "Stripe 请求失败").with_source(err))?;
|
||||
|
||||
let status = resp.status();
|
||||
let body = resp
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| AppError::new(ErrorCode::Internal, "Stripe 响应读取失败").with_source(err))?;
|
||||
let body = resp.text().await.map_err(|err| {
|
||||
AppError::new(ErrorCode::Internal, "Stripe 响应读取失败").with_source(err)
|
||||
})?;
|
||||
|
||||
if !status.is_success() {
|
||||
tracing::error!(status = %status, body = %body, "Stripe API error");
|
||||
|
||||
Reference in New Issue
Block a user