标注SpacetimeDB超时阶段
为SpacetimeDB客户端超时错误记录阶段信息 同步更新后端超时错误映射 避免方洞背景图导入失败误报
This commit is contained in:
@@ -271,7 +271,7 @@ pub(crate) fn should_skip_asset_operation_billing_for_connectivity(
|
||||
error: &SpacetimeClientError,
|
||||
) -> bool {
|
||||
match error {
|
||||
SpacetimeClientError::ConnectDropped | SpacetimeClientError::Timeout => true,
|
||||
SpacetimeClientError::ConnectDropped | SpacetimeClientError::Timeout(_) => true,
|
||||
SpacetimeClientError::Build(message)
|
||||
| SpacetimeClientError::Procedure(message)
|
||||
| SpacetimeClientError::Runtime(message) => {
|
||||
|
||||
@@ -935,12 +935,17 @@ fn map_big_fish_client_error(error: SpacetimeClientError) -> AppError {
|
||||
StatusCode::BAD_REQUEST
|
||||
}
|
||||
SpacetimeClientError::Runtime(_) => StatusCode::BAD_REQUEST,
|
||||
SpacetimeClientError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
|
||||
_ => StatusCode::BAD_GATEWAY,
|
||||
};
|
||||
|
||||
let message = match &error {
|
||||
SpacetimeClientError::Timeout => "SpacetimeDB 会话读取超时,请稍后重试。".to_string(),
|
||||
SpacetimeClientError::Timeout(stage) => {
|
||||
format!(
|
||||
"SpacetimeDB 会话读取超时({}),请稍后重试。",
|
||||
stage.as_str()
|
||||
)
|
||||
}
|
||||
SpacetimeClientError::ConnectDropped => {
|
||||
"SpacetimeDB 会话连接已断开,请稍后重试。".to_string()
|
||||
}
|
||||
@@ -983,6 +988,8 @@ fn current_timestamp_micros_to_string(value: i64) -> String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use spacetime_client::SpacetimeClientStage;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
@@ -1001,7 +1008,7 @@ mod tests {
|
||||
#[test]
|
||||
fn big_fish_gallery_keeps_timeout_errors_visible() {
|
||||
assert!(!should_soft_fallback_big_fish_gallery(
|
||||
&SpacetimeClientError::Timeout
|
||||
&SpacetimeClientError::Timeout(SpacetimeClientStage::ProcedureResult)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use spacetime_client::SpacetimeClientStage;
|
||||
|
||||
pub(super) fn map_big_fish_session_response(
|
||||
session: BigFishSessionRecord,
|
||||
@@ -237,7 +238,7 @@ pub(super) async fn load_big_fish_session_with_retry(
|
||||
.await
|
||||
{
|
||||
Ok(session) => return Ok(session),
|
||||
Err(error @ SpacetimeClientError::Timeout)
|
||||
Err(error @ SpacetimeClientError::Timeout(_))
|
||||
| Err(error @ SpacetimeClientError::ConnectDropped) => {
|
||||
last_retryable_error = Some(error);
|
||||
if attempt == 0 {
|
||||
@@ -249,7 +250,11 @@ pub(super) async fn load_big_fish_session_with_retry(
|
||||
}
|
||||
}
|
||||
|
||||
Err(last_retryable_error.unwrap_or(SpacetimeClientError::Timeout))
|
||||
Err(
|
||||
last_retryable_error.unwrap_or(SpacetimeClientError::Timeout(
|
||||
SpacetimeClientStage::ProcedureResult,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn map_record_anchor_pack_to_domain(
|
||||
|
||||
@@ -133,7 +133,7 @@ fn map_public_work_client_error(error: SpacetimeClientError) -> AppError {
|
||||
{
|
||||
StatusCode::NOT_FOUND
|
||||
}
|
||||
SpacetimeClientError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::ConnectDropped => StatusCode::SERVICE_UNAVAILABLE,
|
||||
_ => StatusCode::BAD_GATEWAY,
|
||||
};
|
||||
|
||||
@@ -382,7 +382,7 @@ pub(super) fn puzzle_bad_request(
|
||||
pub(super) fn map_puzzle_client_error(error: SpacetimeClientError) -> AppError {
|
||||
let status = match &error {
|
||||
SpacetimeClientError::ConnectDropped => StatusCode::SERVICE_UNAVAILABLE,
|
||||
SpacetimeClientError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
|
||||
error if should_skip_asset_operation_billing_for_connectivity(error) => {
|
||||
StatusCode::SERVICE_UNAVAILABLE
|
||||
}
|
||||
@@ -450,7 +450,7 @@ pub(super) fn map_puzzle_compile_error(error: SpacetimeClientError) -> AppError
|
||||
StatusCode::SERVICE_UNAVAILABLE
|
||||
} else if matches!(
|
||||
error,
|
||||
SpacetimeClientError::ConnectDropped | SpacetimeClientError::Timeout
|
||||
SpacetimeClientError::ConnectDropped | SpacetimeClientError::Timeout(_)
|
||||
) || should_skip_asset_operation_billing_for_connectivity(&error)
|
||||
{
|
||||
StatusCode::SERVICE_UNAVAILABLE
|
||||
@@ -485,7 +485,7 @@ pub(super) fn map_puzzle_compile_error(error: SpacetimeClientError) -> AppError
|
||||
StatusCode::BAD_GATEWAY
|
||||
}
|
||||
SpacetimeClientError::ConnectDropped => StatusCode::SERVICE_UNAVAILABLE,
|
||||
SpacetimeClientError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Runtime(_) => StatusCode::BAD_REQUEST,
|
||||
_ => StatusCode::BAD_GATEWAY,
|
||||
}
|
||||
|
||||
@@ -1604,6 +1604,7 @@ fn is_missing_creation_entry_config_procedure(error: &SpacetimeClientError) -> b
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use module_ai::{AiTaskKind, generate_ai_task_id};
|
||||
use spacetime_client::SpacetimeClientStage;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1618,7 +1619,7 @@ mod tests {
|
||||
&SpacetimeClientError::Procedure("No such procedure".to_string()),
|
||||
));
|
||||
assert!(!is_missing_creation_entry_config_procedure(
|
||||
&SpacetimeClientError::Timeout,
|
||||
&SpacetimeClientError::Timeout(SpacetimeClientStage::ProcedureResult),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -1455,7 +1455,7 @@ fn map_spacetime_error(error: SpacetimeClientError) -> AppError {
|
||||
{
|
||||
StatusCode::FORBIDDEN
|
||||
}
|
||||
SpacetimeClientError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
|
||||
SpacetimeClientError::ConnectDropped => StatusCode::SERVICE_UNAVAILABLE,
|
||||
_ => StatusCode::BAD_GATEWAY,
|
||||
};
|
||||
|
||||
@@ -360,7 +360,7 @@ pub enum SpacetimeClientError {
|
||||
ConnectDropped,
|
||||
Procedure(String),
|
||||
Runtime(String),
|
||||
Timeout,
|
||||
Timeout(SpacetimeClientStage),
|
||||
}
|
||||
|
||||
const DEFAULT_PROCEDURE_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
@@ -711,7 +711,7 @@ impl SpacetimeClient {
|
||||
.map_err(|_| {
|
||||
SpacetimeStageError::new(
|
||||
SpacetimeClientStage::PoolAcquire,
|
||||
SpacetimeClientError::Timeout,
|
||||
SpacetimeClientError::Timeout(SpacetimeClientStage::PoolAcquire),
|
||||
)
|
||||
})?
|
||||
.map_err(|error| {
|
||||
@@ -804,7 +804,7 @@ impl SpacetimeClient {
|
||||
.map_err(|_| {
|
||||
SpacetimeStageError::new(
|
||||
SpacetimeClientStage::ConnectBuild,
|
||||
SpacetimeClientError::Timeout,
|
||||
SpacetimeClientError::Timeout(SpacetimeClientStage::ConnectBuild),
|
||||
)
|
||||
})?
|
||||
.map_err(|error| {
|
||||
@@ -821,7 +821,7 @@ impl SpacetimeClient {
|
||||
.map_err(|_| {
|
||||
SpacetimeStageError::new(
|
||||
SpacetimeClientStage::ConnectHandshake,
|
||||
SpacetimeClientError::Timeout,
|
||||
SpacetimeClientError::Timeout(SpacetimeClientStage::ConnectHandshake),
|
||||
)
|
||||
})?
|
||||
.map_err(|_| {
|
||||
@@ -945,7 +945,7 @@ impl SpacetimeClient {
|
||||
.map_err(|_| {
|
||||
SpacetimeStageError::new(
|
||||
SpacetimeClientStage::ReadModelSubscribe,
|
||||
SpacetimeClientError::Timeout,
|
||||
SpacetimeClientError::Timeout(SpacetimeClientStage::ReadModelSubscribe),
|
||||
)
|
||||
})?
|
||||
.map_err(|_| {
|
||||
@@ -970,7 +970,7 @@ impl SpacetimeClient {
|
||||
// 超时后必须统一归还租约;若连接已先一步断开则回传断线,否则标记坏连接并回传超时。
|
||||
fn resolve_timeout_error(
|
||||
connection: Option<&PooledConnection>,
|
||||
_stage: SpacetimeClientStage,
|
||||
stage: SpacetimeClientStage,
|
||||
) -> SpacetimeClientError {
|
||||
if let Some(connection) = connection {
|
||||
if connection.is_broken() {
|
||||
@@ -979,7 +979,7 @@ impl SpacetimeClient {
|
||||
connection.mark_broken();
|
||||
}
|
||||
|
||||
SpacetimeClientError::Timeout
|
||||
SpacetimeClientError::Timeout(stage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,7 +1127,9 @@ impl fmt::Display for SpacetimeClientError {
|
||||
f.write_str(message)
|
||||
}
|
||||
Self::ConnectDropped => f.write_str("SpacetimeDB 连接在返回结果前已断开"),
|
||||
Self::Timeout => f.write_str("SpacetimeDB procedure 调用超时"),
|
||||
Self::Timeout(stage) => {
|
||||
f.write_str(&format!("SpacetimeDB {} 调用超时", stage.as_str()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1241,6 +1243,6 @@ mod tests {
|
||||
Err(error) => error,
|
||||
};
|
||||
assert_eq!(error.stage, SpacetimeClientStage::PoolAcquire);
|
||||
assert!(matches!(error.error, SpacetimeClientError::Timeout));
|
||||
assert!(matches!(error.error, SpacetimeClientError::Timeout(_)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,7 @@ import {
|
||||
Send,
|
||||
Trash2,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
type ChangeEvent,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { type ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import type { SquareHoleResultDraft } from '../../../packages/shared/src/contracts/squareHoleAgent';
|
||||
import type {
|
||||
@@ -24,6 +18,11 @@ import type {
|
||||
SquareHoleShapeOption,
|
||||
SquareHoleWorkProfile,
|
||||
} from '../../../packages/shared/src/contracts/squareHoleWorks';
|
||||
import {
|
||||
canUseNativeHostCapability,
|
||||
type HostFileImportImageResult,
|
||||
importHostImageFile,
|
||||
} from '../../services/host-bridge/hostBridge';
|
||||
import {
|
||||
publishSquareHoleWork,
|
||||
regenerateSquareHoleWorkImage,
|
||||
@@ -32,14 +31,9 @@ import {
|
||||
type SquareHoleImageAssetKind,
|
||||
updateSquareHoleWork,
|
||||
} from '../../services/square-hole-works';
|
||||
import {
|
||||
canUseNativeHostCapability,
|
||||
type HostFileImportImageResult,
|
||||
importHostImageFile,
|
||||
} from '../../services/host-bridge/hostBridge';
|
||||
import { PlatformActionButton } from '../common/PlatformActionButton';
|
||||
import { PlatformBackActionButton } from '../common/PlatformBackActionButton';
|
||||
import { PlatformAssetPickerGrid } from '../common/PlatformAssetPickerCard';
|
||||
import { PlatformBackActionButton } from '../common/PlatformBackActionButton';
|
||||
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
|
||||
import { PlatformIconButton } from '../common/PlatformIconButton';
|
||||
import { PlatformMediaFrame } from '../common/PlatformMediaFrame';
|
||||
@@ -47,11 +41,11 @@ import { PlatformPillBadge } from '../common/PlatformPillBadge';
|
||||
import { PlatformStatGrid } from '../common/PlatformStatGrid';
|
||||
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
||||
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||
import { PlatformToolModalShell } from '../common/PlatformToolModalShell';
|
||||
import {
|
||||
PlatformSelectField,
|
||||
PlatformTextField,
|
||||
} from '../common/PlatformTextField';
|
||||
import { PlatformToolModalShell } from '../common/PlatformToolModalShell';
|
||||
|
||||
type SquareHoleResultViewProps = {
|
||||
profile: SquareHoleWorkProfile;
|
||||
@@ -792,6 +786,9 @@ export function SquareHoleResultView({
|
||||
setEditState((current) => applyImageSlotSrc(current, slot, dataUrl));
|
||||
setLocalError(null);
|
||||
} catch (caughtError) {
|
||||
if (slot.kind === 'background') {
|
||||
return;
|
||||
}
|
||||
setLocalError(
|
||||
caughtError instanceof Error ? caughtError.message : '图片读取失败。',
|
||||
);
|
||||
@@ -823,6 +820,9 @@ export function SquareHoleResultView({
|
||||
);
|
||||
setLocalError(null);
|
||||
} catch (caughtError) {
|
||||
if (slot.kind === 'background') {
|
||||
return;
|
||||
}
|
||||
setLocalError(
|
||||
caughtError instanceof Error ? caughtError.message : '图片读取失败。',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user