@ appport/ 核心
能力运行时间:登记、发送管道、审定、会话、, 事件、溪流、操作和遥测.
Core对HTTP,WebSocket,IPC或任何存储引擎一无所知.
import { createApplication, defineCapability, defineEvent } from "@appport/core";
import { s } from "@appport/schema";
const application = createApplication({
application: { id: "com.example.docs", name: "Docs", version: "1.0.0" },
capabilities: [documentsSave],
events: [documentsChanged],
authorizer: permissionAuthorizer()
});
const response = await application.handleRequest(envelope, { session, transport: "http" });
输油管
receive -> validate -> authorize -> execute -> serialize -> respond
授权总是先于特权逻辑。 输入在 授权,所以政策会看到完善的输入. 输出也经过验证,所以 操作者不能无声地打破其公布的合同.
运行时间提供
- 书记官处和清单 - 申请合同,作为JSON Schema提交.
- 申请登记 确定申请、核实申请和登记申请 有身份、身份、指纹和核查状态的持久追踪.
- 活动 ——最多一次发布,并附有有效载荷验证.
- 流线 - 同步移动或
context.createStream(),取消. - 会议 ——运输中性,可插件存储.
- 目 录 - 重新播放对宣布支助能力的回应,包括 处理者运行前编写的持久在建工程索赔(见下文).
- 货币 —— 说
parallel, (中文(简体) ),serialized,或keyed(field)。 。 。 . - 超时 ——每个能力和每个请求,被服务器夹住.
- 业务 —— 说
operations.status, (中文(简体) ),operations.cancel, (中文(简体) ),operations.events工作超过要求. - 遥测 识别特征和结果,从不合格或有效载荷.
- 卫生 生产错误没有堆放痕迹、路径或秘密.
保留 appport.manifest 财务报告和审定财务报表 appport.ping 能力已登记
自动的,因此发现在没有URL的传输上同样有效.
同上(第13.1节)
能力 idempotency: "supported",请求附有 idempotencyKey 实值
由呼叫者负责(会议,或 principal:<id>并受其请求摘要的约束.
- 说法. 处理器运行前,运行时间会写一个
IdempotencyClaim(单位:千美元)key, (中文(简体) ),requestId, (中文(简体) ),requestDigest范围,claimedAt, (中文(简体) ),expiresAt, (中文(简体) ),status: "in-progress"与store.claim()原子创造,如果没有. - 记录. 关于成功,它写道
IdempotencyRecord与store.set(),哪个 替换索赔。 同声回放得到存储的响应. - 已知失败. 当处理者投掷(或从未启动)时,索赔要求是
与
store.release()并进行重试,不记录失败, 和以前一样. - 未知结果. 在处理器运行时超时或取消时, 失败
返回后(输出验证,状态承诺)或无法保存的记录
写着, 索赔保留下来。 重放则失败
CONFLICT, (中文(简体) ),details.reason: "IDEMPOTENCY_OUTCOME_UNKNOWN"(单位:千美元)IdempotencyOutcomeUnknownError, (中文(简体) ), 与原样requestId),处理者是 没有 再来一次 一样 答案跟随效果和记录之间的进程崩溃,条件是 商店是耐用的。 索赔持续到expiresAt(24小时)或直至操作员 决定store.set(record)或者说store.release({ key, requestId })· ;store.findByRequestId(requestId)发现它.
一项索赔或记录之下的不同请求是: CONFLICT 编号 :
IDEMPOTENCY_KEY_REUSED. 发送到一个能力而无一能支持的密钥
在开发过程中被拒绝INVALID_REQUEST 编号 : IDEMPOTENCY_KEY_UNSUPPORTED和
生产中每个容量版本记录一次;设定
unsupportedIdempotencyKey: "reject" | "warn" 选择.
库存合同. get 财务报告和审定财务报表 set 需要这样做. claim 财务报告和审定财务报表 release 可选
联合起来(只有一家商店申请被拒绝)。 商店没有
保存1.4前的保证:重复在一个过程中被复制
只有,在效果和记录之间发生相撞,可以再次重放执行.
findByRequestId 是可选的,只供运算符使用. MemoryIdempotencyStore
全部执行; 持久存储属于应用程序并可被检查
与 runIdempotencyStoreConformance 从 @appport/testing。 。 。 .
申请登记(PR20)
定义、核实和登记持久跟踪的应用程序:
import { defineApplication, ApplicationRegistry, MemoryApplicationStateStore } from "@appport/core";
// 1. Define an application (PR18)
const application = defineApplication({
identity: { id: "invoicing", name: "Invoicing", version: "1.0.0" },
provides: [invoiceCreate, invoiceSend],
requires: [{ name: "payments.charge", version: 1 }],
implementations: { "invoice.create@1": createImpl, "invoice.send@1": sendImpl }
});
// 2. Verify the application (PR19)
const verification = application.verify();
if (!verification.ready) throw new Error("Application verification failed");
// 3. Get the canonical manifest and fingerprint (PR19)
const manifest = application.manifest();
const fingerprint = application.fingerprint();
// 4. Register for durable tracking (PR20)
const store = new MemoryApplicationStateStore();
const registry = new ApplicationRegistry(store);
const registered = await registry.register({
identity: application.identity,
manifest,
fingerprint,
verification
});
// Tracked application state with identity, manifest, fingerprint, verification
console.log(registered.id, registered.status, registered.revision);
注册的申请状态是可移植的,没有执行 细节——只有合同、身份、核查状态和生命周期.
供应商生命周期和移交
分辨率遵循提供者生命周期状态。 在符合要求的供应商中 active (促进)
一个排除那些只是 registered,所以一个准备好的替代 永远不会取代或模糊提供者
服务中。 没有主动提供者,注册提供者将一如既往地解决;两个主动提供者含糊不清;已退休
供应商从来不是候选人,即使被身份证明所左右.
为了取代一个提供者,用自己的身份和赠款来准备替换,然后在原子的一个步骤中交出:
import { ApplicationLifecycleOperations, ApplicationRegistryLifecycleGateway, MemoryApplicationLifecycleStore } from "@appport/core";
const lifecycle = new ApplicationLifecycleOperations(
new MemoryApplicationLifecycleStore(),
new ApplicationRegistryLifecycleGateway(registry, verifyReplacement) // validation and promotion checks
);
await lifecycle.define(replacement.manifest());
await lifecycle.validate("payments.v2"); // verifyReplacement runs here
await lifecycle.register("payments.v2"); // registered: does not compete with the active provider
await grants.grant({ consumerId: "shop", providerId: "payments.v2", capabilityName: "payments.charge", capabilityVersion: 1 });
const { handover } = await lifecycle.handover("payments.v1", "payments.v2", {
capability: { name: "payments.charge", version: 1 },
authorization: grants // every consumer granted payments.v1 must hold its own grant for payments.v2
});
// payments.v1 is retired and payments.v2 active, in one conditional store write.
ApplicationRegistry.handover() 是下面的原始注册: 它检查两个注册是预期的
在预期的州,如果有同样的能力合同,则一个退休,另一个通过
存储可选 replaceIfCurrent (由 MemoryApplicationStateStore;没有它的商店被拒绝
atomic-store-unsupported) (中文(简体) ). 每一次拒绝都是 ProviderHandoverRejected 带有 reason 改变什么.
在执行之前,包括何时,拒绝援引对前提供方发出的约束力
交接土地经过约束权限检查。 已经交给前供应商的工作在那里完成
移交不会排出或取消。 保证和限制: docs/architecture/provider-handover.md。 。 。 .
警械能力(1.3.0)
企业能力可以具有自己的特性:a 警犬合同,独立发布,不管是否有任何东西执行
这个 申请以自己的名义予以执行 索赔 * 对警犬能力的要求只能解决
通过一项索赔,该索赔被评为: valid规格: spec/fulfillment-1.md 在仓库.
import { CanonicalContractRegistry, ApplicationDependencyResolver, CapabilityBinder, defineCapability, resolvedDependency } from "@appport/core";
import { claimFor } from "@appport/protocol";
const contracts = new CanonicalContractRegistry();
await contracts.register(ordersContract); // a manifest advertising appport.canonical-contract/1, serving no transport
await contracts.activate("org.example.orders");
// A provider implements order.hold@1 under its own name, and claims it (the claim pins the canonical revision by digest).
const hold = defineCapability({ name: "oms.hold", version: 1, authorization: ["orders.hold"], fulfills: [claimFor(ordersContract, "order.hold", 1)], /* … */ });
const resolver = new ApplicationDependencyResolver(registry, { contracts, authorityDecisions });
const candidates = await resolver.discoverCanonical({ contract: "org.example.orders", capability: "order.hold", versionConstraint: "^1" });
const result = await resolver.resolveRequirement({ name: "order.hold", version: 1, versionConstraint: "^1", canonical: { contract: "org.example.orders" } });
if (result.kind === "resolved") {
result.capability.name; // "oms.hold": invocation targets the provider's own capability
resolvedDependency(result); // lock-ready: contract revision and digests, provider registration, claim outcome
await binder.bindResolution(consumer, result); // authorizes oms.hold; result.canonical travels beside it
}
- 合同对供应商. 合同存在于
CanonicalContractRegistry,从来没有在ApplicationRegistry: 可以发现 但从未解决、约束或援引。 供应商的能力是运行. - 对索赔进行评价,不可信.
discoverCanonical根据合同的当前修订对每一项索赔进行估价evaluateFulfillment。仅限valid索赔符合条件;unverified, (中文(简体) ),stale财务报告和审定财务报表invalid他们的发现被退回 A 类 从犬科许可到提供者许可的绘图只有在提供者强制执行犬科许可本身或 明确AuthorityEquivalence裁决予以确立. - 没有名字匹配 . 犬科的要求永远无法解决 能力,因为它有 相同的名称, 犬科和只命名
声明从不满足对方。 报告两个符合条件的供应商为:
ambiguous。 。 。 . - 三个身份. 能力身份(合同、能力、主要版本、摘要)、供应商身份(申请、登记、,
指纹、自身能力)和授权是分开的。 一项索赔没有给予赔偿:有约束力的政策认为 供应商
能力(
capabilityName, (中文(简体) ),capabilityVersion)),赠款必须注明姓名,并注明在context.canonical。 。 。 . - 装订出的证据. 犬科约束要求所附的解决者提供证据(
result.canonical合同编号、修订和contractDigest,犬类capabilityDigest、供应商登记和指纹、索赔及其valid状况,以及所需 和强制许可。 失踪、伪造或不匹配的证据被拒绝(provider_not_authorized) (中文(简体) ). - 什么使约束无效. 任何新的合同修订(不同)
contractDigest,即使所声称的能力保持不变)a 退休合同,或重新登记或退休的提供者。 在执行之前,在援引围栏上拒绝接受约束; 决心再次评估目前的修订.
限制: 权威等同决定提供给解决者,而不是存储,因此,约束在改变时不会重新确认 同步取出栅栏是每个登记册实例.