@ riestools/ aries- dapp- core (日语)
App后端核心:全流程的提供者定位器,可插接的还原器,相通
用于 S3/R2 备份索引的生成出版物和存量 DappActor
计时器。 设计用途 仅限出境 生产指数(无公众入境)
关于计算过程的API)以及当地 aries dapp 发展
修补.
发展与生产
| 表面 | 目的 |
|---|---|
aries-dapp-server 宾+ noopReducer | 仅当地发展 - 嵌入式 s3rver 通过 @ariestools/aries-dapp-serve,内存支持,没有真正的衍生 |
| 项目所属入境点+实际裁减点 | 生产 ——注入S3/R2客户端,将逻辑角色绑定到桶/前缀上,发布不可变的世代 |
dapp-serve 而"Noop"守护进程仍然是明确的本地工具. 生产使用
是一个 项目所属 创建此软件包的可执行文件; dappcore does
不动态加载任意的还原模块,也不存储应用程序
授权(签署种子、 Webb 控制器根等).
已公布状态和索引为 可重建预测而不是权威. 不可认为公共桶对简洁的私人材料是安全的.
块
AbstractActor- 创建/启动/停止生命周期,不重叠计时器 (单位:千美元)firstRunDelay是第一次通过之前的真正延迟,中止信号开启 停机,可选停机 飞行工作,准备合同.DappProviderLocator编号 :createDappLocator——全过程定位. 一个 共享不同角色的 S3 客户端,或 每名客户 最低特权 主; 逻辑角色 → 物理桶 + 前缀 + 可选的公用CDN基. 这个 数据 角色默认只登记为只读( e)put- 扔下来).DappObjectReader编号 :DappObjectWriter编号 :DappBucketStore能力 拆分: 减号见data; 状态/索引仍然是作者. 获取/getWithMeta/stat/put(元数据+有条件写作)/list */destroy.publishGeneration编号 :readPublishedHead——有栅栏的出版物:只创建 生成对象, 以conditional-headCAS或注入式租赁 (或unfenced仅用于本地 s3rver). 回返{ ok: true, … }或者说{ ok: false, conflict }。 。 。 .writeIndexerStatus编号 :readIndexerStatus- 耐用地板/装饰, 已完成位置、观测到源头、生成、成功/错误 时间戳,连续的失败(CDN- revalidate).DappActor- 驱动器 aDappReducer间隔; 可选状态 出版; 可选maxConsecutiveFailures用于主管重新启动.bootDappActors- 开始N演员,准备就绪,停止早期演员 如果后来一个失败.
生产成分(仅限出口)
import { S3Client } from '@aws-sdk/client-s3'
import {
bootDappActors,
createDappLocator,
publishGeneration,
type DappReducer,
} from '@ariestools/aries-dapp-core'
const client = new S3Client({
region: 'auto',
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
forcePathStyle: true,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
},
})
const locator = createDappLocator({
client,
ownClient: true,
bindings: {
data: {
bucket: 'my-dapp',
prefix: 'data',
publicBaseUrl: 'https://cdn.example.com/data',
},
state: {
bucket: 'my-dapp',
prefix: 'state',
publicBaseUrl: 'https://cdn.example.com/state',
},
index: {
bucket: 'my-dapp',
prefix: 'index',
publicBaseUrl: 'https://cdn.example.com/index',
},
},
})
const reducer: DappReducer = {
name: 'my-app-indexer',
version: '1',
async reduce({ state, index, signal, logger }) {
const published = await publishGeneration({
state,
index,
safety: { mode: 'conditional-head' }, // fail closed if provider lacks CAS
// expectedHeadEtag: prior?.headEtag,
reducer: { name: 'my-app-indexer', version: '1' },
source: { cursor: '…', completedPosition: '…', observedHead: '…' },
stateObjects: [{ key: 'view.json', body: '{}', contentType: 'application/json' }],
indexObjects: [{ key: 'by-id.json', body: '{}', contentType: 'application/json' }],
signal,
})
if (!published.ok) {
logger.warn(`publish conflict: ${published.conflict.kind} ${published.conflict.message}`)
return // do not advance checkpoint on conflict
}
logger.info(`published ${published.generation}`)
return {
cursor: '…',
lastCompletedPosition: '…',
observedSourceHead: '…',
generation: published.generation,
generationRoot: published.manifestKey,
}
},
}
const actors = await bootDappActors(locator, [{
name: 'MyIndexer',
reducer,
firstRunDelayMs: 1_000,
reduceIntervalMs: 15_000,
maxConsecutiveFailures: 10,
publishStatus: true,
}])
客户从不联系此进程 。 他们读了 head.json,生成对象,
财务报告和审定财务报表 status.json 从公共CDN/基址。 证书不在
已发布配置和日志.
另见 src/examples/productionComposition.ts。 。 。 .
出版物布局
state/head.json # mutable head (revalidate CDN)
state/status.json # indexer status (revalidate CDN)
state/generations/<id>/manifest.json # immutable
state/generations/<id>/… # immutable state objects
index/generations/<id>/… # immutable index objects
头写了 最后一个。头部离开前的崩溃 生成可见。 检查站不得通过完全公布的检查站 生成( 演员在成功减少后只记录生成) 已发布标题).
本地守护进程( 只编辑)
组装的垃圾桶dist/bin/dappServer.mjs)启动存储服务器和 a
达普达多. aries dapp up 产下它.
国 际
# Empty spine (noop reducer)
aries dapp up
# Real project reducer (ESM .mjs or package export — TypeScript not supported)
aries dapp up --reducer ./dist/indexer.mjs
aries dapp up --reducer ./dist/indexer.mjs --reducer-export myIndex
aries dapp up --reducer @myorg/my-dapp/indexer
# Persist buckets across restarts
aries dapp up --backing disk --data-dir ~/.aries/dapp/data
使用此软件包运出的实例减小器 :
aries dapp up --reducer ./node_modules/@ariestools/aries-dapp-core/examples/countFactsReducer.mjs
# monorepo:
aries dapp up --reducer ./packages/dapp-core/examples/countFactsReducer.mjs
减员模块合同
模块必须导出一个 DappReducer数字 :
- 默认导出,或
- 命名导出
reducer,或 - 任何名称通过
--reducer-export编号 :DAPP_REDUCER_EXPORT
// dist/indexer.mjs
export default {
name: 'my-index',
version: '1',
async reduce({ data, state, index, signal, logger }) {
// read data, publishGeneration / publishIncremental, return progress
},
}
当地出版物应使用 safety: { mode: 'unfenced' } (或荣誉)
DAPP_PUBLICATION_SAFETY,守护进程设定为 unfenced (默认情况下).
s3rver 不支持可靠的CAS头.
信封( 守护)
| 变量 | 默认 | 页:1 |
|---|---|---|
DAPP_PORT | 8801 | |
HOST | 127.0.0.1 | |
DAPP_BACKING | memory | memory | disk |
DAPP_DATA_DIR | ~/.aries/dapp/data | 磁盘根 |
DAPP_REDUCER | (无) | 路径到 .mjs编号 :.js 或包导出 |
DAPP_REDUCER_EXPORT | 默认 / reducer | 命名导出 |
DAPP_REDUCE_INTERVAL_MS | 5000 | |
DAPP_FIRST_RUN_DELAY_MS | 0 | |
DAPP_PUBLICATION_SAFETY | unfenced | 由守护进程为缩小工程设置 |
DAPP_PUBLIC_HOST 编号 : DAPP_TLS_* | --ssl auto |
下 --ssl auto 守护进程通过 NODE_EXTRA_CA_CERTS。 。 。 .
生产入口(不是CLI bin)
执行 没有 运行 aries-dapp-server 或者说 aries dapp up 在生产中。 写一个
项目自有程序:
- 构建一个
S3Client用于 R2/S3( env/IAM 证书—— 从未登录) - 电话
createDappLocator({ client, bindings, ownClient: true }) - 执行a
DappReducer(静态进口——不需要动态CLI载荷) - 电话
bootDappActors与safety: { mode: 'conditional-head' }内部publishGeneration编号 :publishIncremental - SIGTERM的收听和停止演员+
locator.destroy()
见 examples/productionComposition.ts 和上文组成部分.
没有进入的公众听众;客户端从CDN读取头部/状态/对象.
最低优先权IAM/R2注解
- 作家( 私人 API ): 状态/索引需求
s3:GetObject, (中文(简体) ),s3:PutObject,以及 通常s3:ListBucket关于角色前缀。 数据角色 :GetObject编号 :ListBucket仅(无)PutObject) (中文(简体) ). 优先通过createDappLocator({ clients: { data, state, index } })。 。 。 . - 公开CDN: 允许匿名
GET编号 :HEAD只有这个. 拒绝s3:ListBucket财务报告和审定财务报表 全部Put*编号 :Delete*公费 从不要求公开 名单或点. - 全权证书 不得在已发布的标题/显示/状态或日志中出现.
出版安全
| 模式 | 使用 |
|---|---|
conditional-head | 当提供者支持 If-Match / If-None-Match 时生产 |
lease | 用应用喷入式租赁/装配适配器生产 |
unfenced | 只有本地 s3rver / 测试 ——无同时机安全 |
释放、接针、回滚、GC
import {
listReleases, pinRelease, rollbackHead,
planGarbageCollection, runGarbageCollection,
} from '@ariestools/aries-dapp-core'
await pinRelease(state, 'gen-a', { reason: 'hotfix' })
await rollbackHead(state, {
targetGeneration: 'gen-a',
safety: { mode: 'conditional-head' },
expectedHeadEtag: currentEtag,
})
const plan = await planGarbageCollection({
state,
index,
policy: { mode: 'bounded', retainGenerations: 5, cdnGraceMs: 86_400_000 },
})
await runGarbageCollection(plan, { state, index }, { dryRun: true })
来源 数据 从来没有GC'd。 活生生的头,针,和飞行中世代都受到保护.
递增的高心率出版物
用于变化不大的大型指数 publishIncremental (化学文摘社机构+256道)
(原始内容存档于2013-10-29). sharded map.). 未更改的密钥保持稳定 cas/sha256/<hash> URL; 每个通过
只写已更改对象 + 被触摸到的 shards + root + 接收.
import { publishIncremental } from '@ariestools/aries-dapp-core'
const result = await publishIncremental({
state,
index,
safety: { mode: 'conditional-head' },
expectedHeadEtag: prior?.headEtag,
reducer: { name: 'addr-index', version: '1' },
indexChanges: [{ key: 'by-source/0xabc', body: frameJson, contentType: 'application/json' }],
})
浏览器中性消费者
import {
verifyPublishedView, resolveObject,
} from '@ariestools/aries-dapp-core/consumer'
const view = await verifyPublishedView({
fetch,
bases: { state: 'https://cdn.example/state', index: 'https://cdn.example/index' },
})
const one = await resolveObject({
fetch,
bases: { state: 'https://cdn.example/state', index: 'https://cdn.example/index' },
logicalKey: 'by-source/0xabc',
role: 'index',
})
这个子路径上的节点内置或AWS SDK.
R2合同测试
普通CI不需要R2机密. 持全权证书:
export DAPP_R2_CONTRACT_TEST=1
export R2_ACCOUNT_ID=…
export R2_ACCESS_KEY_ID=…
export R2_SECRET_ACCESS_KEY=…
export R2_BUCKET=…
# optional: R2_PUBLIC_BASE_URL=https://pub-….r2.dev
pnpm xy test @ariestools/aries-dapp-core
见 src/spec/r2.contract.spec.ts。 。 。 .