Skip to content

命令与等待结果

CommandClient<C> 是由装饰器实现的传输客户端。send(request, attributes?) 返回 Promise<CommandResult>;sendAndWaitStream 返回 Promise<ReadableStream<JsonServerSentEvent<CommandResult>>>,使用 Accept text/event-stream 和 JSON SSE 提取。必须在 ApiMetadata 和/或 CommandRequest 中提供服务所需端点,不会根据 C 推导通用命令 URL。

请求与等待阶段

CommandRequest 扩展 ParameterRequest;body 为命令可写字段 CommandBody<C>,还可带 path(端点路径覆盖,不是 url)、method、路径参数、头和其他请求数据。CommandHeaders 给出准确 HTTP 头名。头值为字符串,覆盖租户/所有者/空间/聚合归属、预期聚合版本、Request-Id、Local-First、命令 context/name/type、等待超时、stage/context/processor/function 及对应链尾选择器。Command-Header- 是扩展前缀。通用 CommandRequestHeaders 声明把已知头列为必填;常规部分头集合也可通过生成客户端所用的底层请求/元数据选项提供。传输层不会替你生成幂等键或选择等待阶段。

CommandStage表示的信号
SENT命令已发送
PROCESSED命令处理阶段
SNAPSHOT快照阶段
PROJECTED投影阶段
EVENT_HANDLED事件处理器阶段
SAGA_HANDLEDSaga 处理阶段

这些是不同服务端等待目标,并不保证所有下游消费者都已追上。客户端未设置数值等待超时默认值。CommandResult 包含身份、聚合归属、stage、command/request/wait ID、signalTime、可选 aggregateVersion、function、result 映射和 errorCode/errorMsg/bindingErrors。HTTP 成功不等于命令成功,应检查 ErrorCodes.isSucceeded(result.errorCode)WaitSignal 对应信号模型,其 aggregateId 为嵌套对象。BatchResult 含 after/size 与 ErrorInfo,本身不实现批次遍历。

传输或提取失败拒绝 Promise;流错误也可能在初始 Promise 完成后的 reader.read 才出现,提前退出必须取消并释放 reader。DeleteAggregate/RecoverAggregate 是空命令体契约,资源标签命令带 tags;它们在服务端执行端点前不产生删除/恢复效果。

读取命令结果

字段解释
idcommandIdrequestIdwaitCommandId不同的信号/命令/请求/等待关联 ID,不应互相替代服务端幂等键。
contextNameaggregateNametenantIdaggregateIdCommandResult 中是平铺聚合身份;WaitSignal 则嵌套 AggregateId 对象。
stage当前信号的等待阶段,不是覆盖所有投影的布尔成功标记。
aggregateVersion?服务端报告的可选版本;缺失时不能建立可见性屏障。
signalTime数字信号时间戳,不是客户端超时时长。
function处理器/函数元数据,参见消息元数据
result服务端提供的结果映射,不是泛型命令体 C。
errorCodeerrorMsgbindingErrors?业务结果与可选字段错误,参见错误分类

嵌套/平铺身份细节参见身份与归属。结果接口不赋默认值、不验证 JSON。流通过 event.data 携带连续 CommandResult 载荷;初始 HTTP 成功不表示所有事件或阶段均已完成。

完整示例

ts
import { CommandClient, ErrorCodes } from '@ahoo-wang/fetcher-wow';
const client = new CommandClient<{ name: string }>({ basePath: '/users' });
export async function rename() {
  const result = await client.send({
    path: '1/rename',
    method: 'POST',
    body: { name: 'Ada' },
  });
  if (!ErrorCodes.isSucceeded(result.errorCode)) {
    throw new Error(`${result.errorCode}: ${result.errorMsg}`);
  }
  return result;
}

示例中的服务 URL 需要应用实现;类型检查不代表已经访问外部服务。

公开签名与类型

以下签名按当前根入口可达声明核对。? 表示可省略;泛型/接口只约束编译期,继承项与关联类型可从 符号索引 定位。运行时默认值和失败行为以本页上文为准。

CommandClient

ts
export class CommandClient<C extends object = object> implements ApiMetadataCapable {
    constructor(public readonly apiMetadata?: ApiMetadata);
    send(commandRequest: CommandRequest<C>, attributes?: Record<string, any>): Promise<CommandResult>;
    sendAndWaitStream(commandRequest: CommandRequest<C>, attributes?: Record<string, any>): Promise<CommandResultEventStream>;
}

packages/wow/src/command/commandClient.ts:76

CommandHeaders

展开完整字段与成员
ts
export class CommandHeaders {
  static readonly COMMAND_HEADERS_PREFIX = 'Command-';
  static readonly TENANT_ID = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Tenant-Id`;
  static readonly OWNER_ID = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Owner-Id`;
  static readonly SPACE_ID = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Space-Id`;
  static readonly AGGREGATE_ID = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Aggregate-Id`;
  static readonly AGGREGATE_VERSION = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Aggregate-Version`;
  static readonly WAIT_PREFIX = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Wait-`;
  static readonly WAIT_TIME_OUT = `${CommandHeaders.WAIT_PREFIX}Timeout`;
  static readonly WAIT_STAGE = `${CommandHeaders.WAIT_PREFIX}Stage`;
  static readonly WAIT_CONTEXT = `${CommandHeaders.WAIT_PREFIX}Context`;
  static readonly WAIT_PROCESSOR = `${CommandHeaders.WAIT_PREFIX}Processor`;
  static readonly WAIT_FUNCTION = `${CommandHeaders.WAIT_PREFIX}Function`;
  static readonly WAIT_TAIL_PREFIX = `${CommandHeaders.WAIT_PREFIX}Tail-`;
  static readonly WAIT_TAIL_STAGE = `${CommandHeaders.WAIT_TAIL_PREFIX}Stage`;
  static readonly WAIT_TAIL_CONTEXT = `${CommandHeaders.WAIT_TAIL_PREFIX}Context`;
  static readonly WAIT_TAIL_PROCESSOR = `${CommandHeaders.WAIT_TAIL_PREFIX}Processor`;
  static readonly WAIT_TAIL_FUNCTION = `${CommandHeaders.WAIT_TAIL_PREFIX}Function`;
  static readonly REQUEST_ID = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Request-Id`;
  static readonly LOCAL_FIRST = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Local-First`;
  static readonly COMMAND_AGGREGATE_CONTEXT = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Aggregate-Context`;
  static readonly COMMAND_AGGREGATE_NAME = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Aggregate-Name`;
  static readonly COMMAND_TYPE = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Type`;
  static readonly COMMAND_HEADER_X_PREFIX = `${CommandHeaders.COMMAND_HEADERS_PREFIX}Header-`;
}

packages/wow/src/command/commandHeaders.ts:33

CommandRequestHeaders

展开完整字段与成员
ts
export interface CommandRequestHeaders extends RequestHeaders {
  [CommandHeaders.TENANT_ID]: string;
  [CommandHeaders.OWNER_ID]: string;
  [CommandHeaders.SPACE_ID]: string;
  [CommandHeaders.AGGREGATE_ID]: string;
  [CommandHeaders.AGGREGATE_VERSION]: string;
  [CommandHeaders.WAIT_TIME_OUT]: string;
  [CommandHeaders.WAIT_STAGE]: string;
  [CommandHeaders.WAIT_CONTEXT]: string;
  [CommandHeaders.WAIT_PROCESSOR]: string;
  [CommandHeaders.WAIT_FUNCTION]: string;
  [CommandHeaders.WAIT_TAIL_STAGE]: string;
  [CommandHeaders.WAIT_TAIL_CONTEXT]: string;
  [CommandHeaders.WAIT_TAIL_PROCESSOR]: string;
  [CommandHeaders.WAIT_TAIL_FUNCTION]: string;
  [CommandHeaders.REQUEST_ID]: string;
  [CommandHeaders.LOCAL_FIRST]: string;
  [CommandHeaders.COMMAND_AGGREGATE_CONTEXT]: string;
  [CommandHeaders.COMMAND_AGGREGATE_NAME]: string;
  [CommandHeaders.COMMAND_TYPE]: string;
}

packages/wow/src/command/commandRequest.ts:36

CommandUrlParams

ts
export interface CommandUrlParams extends Omit<UrlParams, 'path' | 'query'> {
  path?: UrlPathParams;
}

packages/wow/src/command/commandRequest.ts:148

CommandRequest

ts
export interface CommandRequest<
  C extends object = object,
> extends ParameterRequest<CommandBody<C>> {
  urlParams?: CommandUrlParams;
  headers?: CommandRequestHeaders;
  body?: CommandBody<C>;
}

packages/wow/src/command/commandRequest.ts:158

WaitSignal

ts
export interface WaitSignal
  extends
    Identifier,
    WaitCommandIdCapable,
    CommandId,
    AggregateIdCapable,
    NullableAggregateVersionCapable,
    ErrorInfo,
    SignalTimeCapable,
    CommandResultCapable,
    FunctionInfoCapable {}

packages/wow/src/command/commandResult.ts:52

CommandResult

ts
export interface CommandResult
  extends
    Identifier,
    WaitCommandIdCapable,
    CommandStageCapable,
    NamedBoundedContext,
    AggregateNameCapable,
    AggregateId,
    ErrorInfo,
    CommandId,
    RequestId,
    ErrorInfo,
    FunctionInfoCapable,
    CommandResultCapable,
    SignalTimeCapable,
    NullableAggregateVersionCapable {}

packages/wow/src/command/commandResult.ts:74

CommandResultArray

ts
export type CommandResultArray = CommandResult[];

packages/wow/src/command/commandResult.ts:91

CommandResultEventStream

ts
export type CommandResultEventStream = ReadableStream<
  JsonServerSentEvent<CommandResult>
>;

packages/wow/src/command/commandResult.ts:108

CommandId

ts
export interface CommandId {
  commandId: string;
}

packages/wow/src/command/types.ts:27

WaitCommandIdCapable

ts
export interface WaitCommandIdCapable {
  waitCommandId: string;
}

packages/wow/src/command/types.ts:36

RequestId

ts
export interface RequestId {
  requestId: string;
}

packages/wow/src/command/types.ts:45

CommandStage

ts
export enum CommandStage {
  SENT = 'SENT',
  PROCESSED = 'PROCESSED',
  SNAPSHOT = 'SNAPSHOT',
  PROJECTED = 'PROJECTED',
  EVENT_HANDLED = 'EVENT_HANDLED',
  SAGA_HANDLED = 'SAGA_HANDLED',
}

packages/wow/src/command/types.ts:54

CommandStageCapable

ts
export interface CommandStageCapable {
  stage: CommandStage;
}

packages/wow/src/command/types.ts:91

CommandResultCapable

ts
export interface CommandResultCapable {
  result: Record<string, any>;
}

packages/wow/src/command/types.ts:100

SignalTimeCapable

ts
export interface SignalTimeCapable {
  signalTime: number;
}

packages/wow/src/command/types.ts:109

NullableAggregateVersionCapable

ts
export interface NullableAggregateVersionCapable {
  aggregateVersion?: number;
}

packages/wow/src/command/types.ts:118

CompensationTarget

ts
export interface CompensationTarget
  extends PartialBy<Identifier, 'id'>, FunctionInfoCapable {}

packages/wow/src/command/types.ts:135

DeleteAggregate

ts
export interface DeleteAggregate {}

packages/wow/src/command/types.ts:146

CommandBody

ts
export type CommandBody<C> = RemoveReadonlyFields<C>;

packages/wow/src/command/types.ts:148

DeleteAggregateCommand

ts
export type DeleteAggregateCommand = CommandBody<DeleteAggregate>;

packages/wow/src/command/types.ts:150

RecoverAggregate

ts
export interface RecoverAggregate {}

packages/wow/src/command/types.ts:160

RecoverAggregateCommand

ts
export type RecoverAggregateCommand = CommandBody<RecoverAggregate>;

packages/wow/src/command/types.ts:162

ApplyResourceTags

ts
export interface ApplyResourceTags extends ApplyAbacTags {}

packages/wow/src/command/types.ts:165

ApplyResourceTagsCommand

ts
export type ApplyResourceTagsCommand = CommandBody<ApplyResourceTags>;

packages/wow/src/command/types.ts:167

BatchResult

ts
export interface BatchResult extends ErrorInfo {
  after: string;
  size: number;
}

packages/wow/src/command/types.ts:175

相关专题

客户端配置与元数据 · 快照查询 · 过滤表达式与旧条件 · 投影、排序与分页 · 游标查询 · 聚合构造器 · 事件与历史状态 · 身份与资源归属

基于 Apache License 2.0 发布。