Files
Genarrative/server-rs/crates/module-game-distribution/src/errors.rs
T
suzmii 3aa3e33ceb
Project CI / AI game creator shell Rust crates (pull_request) Failing after 56s
Project CI / Backend tests (pull_request) Failing after 23s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 5m7s
Project CI / Repository checks (pull_request) Failing after 21s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
实现统一项目发行版本
以 projectVersion 作为 AGC 唯一用户版本,支持同版本重复提交和版本回退。

保留 publicationRevision 并发校验与旧客户端自动递增兼容。
2026-10-03 16:41:04 +08:00

110 lines
4.2 KiB
Rust

use std::{error::Error, fmt};
use crate::{GameVersionStatus, GameVisibility};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum GameDistributionFieldError {
MissingGameId,
MissingVersionId,
MissingOwnerUserId,
MissingActorUserId,
MissingIdempotencyKey,
MissingRequestDigest,
InvalidPackageDigest,
InvalidPackageBytes,
MissingReviewReason,
InvalidVersionNumber,
VersionNumberExhausted,
}
impl fmt::Display for GameDistributionFieldError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match self {
Self::MissingGameId => "gameId 不能为空",
Self::MissingVersionId => "versionId 不能为空",
Self::MissingOwnerUserId => "ownerUserId 不能为空",
Self::MissingActorUserId => "actorUserId 不能为空",
Self::MissingIdempotencyKey => "Idempotency-Key 不能为空",
Self::MissingRequestDigest => "request digest 不能为空",
Self::InvalidPackageDigest => "packageSha256 必须是 64 位十六进制摘要",
Self::InvalidPackageBytes => "packageBytes 必须大于 0",
Self::MissingReviewReason => "拒绝审核必须提供理由",
Self::InvalidVersionNumber => "版本号必须是大于 0 的整数",
Self::VersionNumberExhausted => "版本号已达上限,无法自动递增",
};
formatter.write_str(message)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum GameDistributionError {
Field(GameDistributionFieldError),
GameNotFound,
VersionNotFound,
GameAlreadyExists,
VersionAlreadyExists,
Forbidden,
IdempotencyConflict,
IdempotencyOutcomeMismatch,
InvalidVersionTransition {
from: GameVersionStatus,
to: GameVersionStatus,
},
PublicationConflict {
expected: u64,
actual: u64,
},
PackageMismatch,
GameSuspended,
GameNotPublished,
VersionNotPublished,
VersionAlreadyPublished,
ReviewActionNotAllowed,
}
impl fmt::Display for GameDistributionError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Field(field) => field.fmt(formatter),
Self::GameNotFound => formatter.write_str("游戏不存在"),
Self::VersionNotFound => formatter.write_str("游戏版本不存在"),
Self::GameAlreadyExists => formatter.write_str("游戏已存在"),
Self::VersionAlreadyExists => formatter.write_str("游戏版本已存在"),
Self::Forbidden => formatter.write_str("无权操作该游戏"),
Self::IdempotencyConflict => formatter.write_str("幂等键对应的请求摘要不一致"),
Self::IdempotencyOutcomeMismatch => formatter.write_str("幂等记录结果类型不一致"),
Self::InvalidVersionTransition { from, to } => {
write!(formatter, "版本状态不能从 {from:?} 变为 {to:?}")
}
Self::PublicationConflict { expected, actual } => {
write!(
formatter,
"公开状态版本冲突:期望 {expected},实际 {actual}"
)
}
Self::PackageMismatch => formatter.write_str("发行包摘要或字节数与版本声明不一致"),
Self::GameSuspended => formatter.write_str("游戏已被管理员下架"),
Self::GameNotPublished => formatter.write_str("游戏当前未公开"),
Self::VersionNotPublished => formatter.write_str("游戏版本当前未公开"),
Self::VersionAlreadyPublished => formatter.write_str("游戏版本已经公开"),
Self::ReviewActionNotAllowed => formatter.write_str("当前版本不允许审核操作"),
}
}
}
impl Error for GameDistributionError {}
impl From<GameDistributionFieldError> for GameDistributionError {
fn from(value: GameDistributionFieldError) -> Self {
Self::Field(value)
}
}
#[allow(dead_code)]
fn _visibility_is_exhaustive(visibility: GameVisibility) -> bool {
matches!(
visibility,
GameVisibility::Unpublished | GameVisibility::Published | GameVisibility::Suspended
)
}