53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import { DomainError } from "./domain-error.ts";
|
|
|
|
export type RelayPlacementRouteRecord = {
|
|
tenant_id: string;
|
|
tenant_status: string;
|
|
home_region: string;
|
|
relay_node_id: string | null;
|
|
generation: number;
|
|
placement_state: string;
|
|
authorization_revision: number;
|
|
internal_endpoint_ref?: string | null;
|
|
relay_node_status?: string | null;
|
|
};
|
|
|
|
export type RelayRouteResolution = {
|
|
relay_node_id: string;
|
|
placement_generation: number;
|
|
home_region: string;
|
|
local: boolean;
|
|
endpoint_ref?: string;
|
|
};
|
|
|
|
export function isWritableRelayPlacement(
|
|
placementState: string | null | undefined,
|
|
relayNodeStatus: string | null | undefined,
|
|
): boolean {
|
|
return ["active", "draining"].includes(placementState ?? "") && relayNodeStatus === "active";
|
|
}
|
|
|
|
export function resolveRelayPlacementRoute(
|
|
placement: RelayPlacementRouteRecord,
|
|
currentNodeId: string,
|
|
): RelayRouteResolution {
|
|
if (!placement.relay_node_id || !["active", "draining"].includes(placement.placement_state)) {
|
|
throw new DomainError("service_provisioning", "租户 Relay 正在准备", 503, true, 5);
|
|
}
|
|
if (placement.relay_node_status !== "active") {
|
|
throw new DomainError("region_unavailable", "目标 Relay 节点当前不可用", 503, true, 5);
|
|
}
|
|
const local = placement.relay_node_id === currentNodeId;
|
|
const endpointRef = placement.internal_endpoint_ref?.trim() ?? "";
|
|
if (!local && !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(endpointRef)) {
|
|
throw new DomainError("route_unavailable", "目标 Relay 内部路由不可用", 503, true, 5);
|
|
}
|
|
return {
|
|
relay_node_id: placement.relay_node_id,
|
|
placement_generation: placement.generation,
|
|
home_region: placement.home_region,
|
|
local,
|
|
...(local ? {} : { endpoint_ref: endpointRef }),
|
|
};
|
|
}
|