Files
Genarrative/server-rs/crates/spacetime-client/src/mapper/external_generation.rs
kdletters 951caac32d 扩展外部生成Worker队列
新增外部生成队列概览和单任务状态契约

将跳一跳、拼消消、敲木鱼图片生成动作接入worker队列

前端生成等待页展示当前任务和队列数量

更新外部生成worker运维文档和团队决策记录
2026-06-12 23:15:55 +08:00

256 lines
8.5 KiB
Rust

use super::*;
impl From<ExternalGenerationJobEnqueueRecordInput> for ExternalGenerationJobEnqueueInput {
fn from(input: ExternalGenerationJobEnqueueRecordInput) -> Self {
Self {
job_id: input.job_id,
dedupe_key: input.dedupe_key,
job_kind: input.job_kind,
owner_user_id: input.owner_user_id,
source_module: input.source_module,
source_entity_id: input.source_entity_id,
request_label: input.request_label,
request_payload_json: input.request_payload_json,
max_attempts: input.max_attempts,
available_at_micros: input.available_at_micros,
created_at_micros: input.created_at_micros,
}
}
}
impl From<ExternalGenerationJobClaimRecordInput> for ExternalGenerationJobClaimInput {
fn from(input: ExternalGenerationJobClaimRecordInput) -> Self {
Self {
worker_id: input.worker_id,
limit: input.limit,
lease_expires_at_micros: input.lease_expires_at_micros,
claimed_at_micros: input.claimed_at_micros,
}
}
}
impl From<ExternalGenerationJobCompleteRecordInput> for ExternalGenerationJobCompleteInput {
fn from(input: ExternalGenerationJobCompleteRecordInput) -> Self {
Self {
job_id: input.job_id,
worker_id: input.worker_id,
lease_token: input.lease_token,
result_payload_json: input.result_payload_json,
completed_at_micros: input.completed_at_micros,
}
}
}
impl From<ExternalGenerationJobRenewLeaseRecordInput> for ExternalGenerationJobRenewLeaseInput {
fn from(input: ExternalGenerationJobRenewLeaseRecordInput) -> Self {
Self {
job_id: input.job_id,
worker_id: input.worker_id,
lease_token: input.lease_token,
lease_expires_at_micros: input.lease_expires_at_micros,
renewed_at_micros: input.renewed_at_micros,
}
}
}
impl From<ExternalGenerationJobFailRecordInput> for ExternalGenerationJobFailInput {
fn from(input: ExternalGenerationJobFailRecordInput) -> Self {
Self {
job_id: input.job_id,
worker_id: input.worker_id,
lease_token: input.lease_token,
error_message: input.error_message,
retry_after_micros: input.retry_after_micros,
failed_at_micros: input.failed_at_micros,
}
}
}
impl From<ExternalGenerationJobGetRecordInput> for ExternalGenerationJobGetInput {
fn from(input: ExternalGenerationJobGetRecordInput) -> Self {
Self {
job_id: input.job_id,
owner_user_id: input.owner_user_id,
}
}
}
pub(crate) fn map_external_generation_job_procedure_result(
result: ExternalGenerationJobProcedureResult,
) -> Result<ExternalGenerationJobRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let job = result
.job
.ok_or_else(|| SpacetimeClientError::missing_snapshot("external_generation_job 快照"))?;
Ok(map_external_generation_job_snapshot(job))
}
pub(crate) fn map_external_generation_job_claim_result(
result: ExternalGenerationJobProcedureResult,
) -> Result<Vec<ExternalGenerationJobRecord>, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
Ok(result
.jobs
.into_iter()
.map(map_external_generation_job_snapshot)
.collect())
}
pub(crate) fn map_external_generation_queue_stats_result(
result: ExternalGenerationQueueStatsProcedureResult,
) -> Result<ExternalGenerationQueueStatsRecord, SpacetimeClientError> {
if !result.ok {
return Err(SpacetimeClientError::procedure_failed(result.error_message));
}
let stats = result.stats.ok_or_else(|| {
SpacetimeClientError::missing_snapshot("external_generation queue stats 快照")
})?;
Ok(ExternalGenerationQueueStatsRecord {
pending_count: stats.pending_count,
delayed_pending_count: stats.delayed_pending_count,
claimable_pending_count: stats.claimable_pending_count,
running_active_count: stats.running_active_count,
expired_running_count: stats.expired_running_count,
terminal_count: stats.terminal_count,
claimable_count: stats.claimable_count,
oldest_claimable_age_micros: stats.oldest_claimable_age_micros,
now_micros: stats.now_micros,
})
}
fn map_external_generation_job_snapshot(
snapshot: ExternalGenerationJobSnapshot,
) -> ExternalGenerationJobRecord {
ExternalGenerationJobRecord {
job_id: snapshot.job_id,
dedupe_key: snapshot.dedupe_key,
job_kind: snapshot.job_kind,
owner_user_id: snapshot.owner_user_id,
source_module: snapshot.source_module,
source_entity_id: snapshot.source_entity_id,
request_label: snapshot.request_label,
request_payload_json: snapshot.request_payload_json,
status: snapshot.status,
attempt: snapshot.attempt,
max_attempts: snapshot.max_attempts,
last_error_message: snapshot.last_error_message,
worker_id: snapshot.worker_id,
lease_expires_at: snapshot
.lease_expires_at_micros
.map(format_timestamp_micros),
available_at: format_timestamp_micros(snapshot.available_at_micros),
result_payload_json: snapshot.result_payload_json,
created_at: format_timestamp_micros(snapshot.created_at_micros),
started_at: snapshot.started_at_micros.map(format_timestamp_micros),
completed_at: snapshot.completed_at_micros.map(format_timestamp_micros),
updated_at: format_timestamp_micros(snapshot.updated_at_micros),
updated_at_micros: snapshot.updated_at_micros,
lease_token: snapshot.lease_token,
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobEnqueueRecordInput {
pub job_id: String,
pub dedupe_key: String,
pub job_kind: String,
pub owner_user_id: String,
pub source_module: String,
pub source_entity_id: String,
pub request_label: String,
pub request_payload_json: String,
pub max_attempts: u32,
pub available_at_micros: i64,
pub created_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobClaimRecordInput {
pub worker_id: String,
pub limit: u32,
pub lease_expires_at_micros: i64,
pub claimed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobCompleteRecordInput {
pub job_id: String,
pub worker_id: String,
pub lease_token: String,
pub result_payload_json: Option<String>,
pub completed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobRenewLeaseRecordInput {
pub job_id: String,
pub worker_id: String,
pub lease_token: String,
pub lease_expires_at_micros: i64,
pub renewed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobFailRecordInput {
pub job_id: String,
pub worker_id: String,
pub lease_token: String,
pub error_message: String,
pub retry_after_micros: i64,
pub failed_at_micros: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobGetRecordInput {
pub job_id: String,
pub owner_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationJobRecord {
pub job_id: String,
pub dedupe_key: String,
pub job_kind: String,
pub owner_user_id: String,
pub source_module: String,
pub source_entity_id: String,
pub request_label: String,
pub request_payload_json: String,
pub status: String,
pub attempt: u32,
pub max_attempts: u32,
pub last_error_message: Option<String>,
pub worker_id: Option<String>,
pub lease_expires_at: Option<String>,
pub available_at: String,
pub result_payload_json: Option<String>,
pub created_at: String,
pub started_at: Option<String>,
pub completed_at: Option<String>,
pub updated_at: String,
pub updated_at_micros: i64,
pub lease_token: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExternalGenerationQueueStatsRecord {
pub pending_count: u32,
pub delayed_pending_count: u32,
pub claimable_pending_count: u32,
pub running_active_count: u32,
pub expired_running_count: u32,
pub terminal_count: u32,
pub claimable_count: u32,
pub oldest_claimable_age_micros: Option<i64>,
pub now_micros: i64,
}