条目注册表
查询和修改已注册条目。访问元数据、快照和版本历史。
加载
local registry = require("registry")
条目结构
{
id = "app.lib:assert", -- string: "namespace:name"
kind = "function.lua", -- string: 条目类型
meta = {type = "test"}, -- table: 可搜索元数据
data = {...} -- any: 条目负载
}
从 registry.get、registry.find、snap:entries()、snap:get()、snap:namespace() 和 snap:find() 读回的条目只携带这四个面向作者的字段。
dependency_root 是 changes:create() 和 changes:update() 接受的写入侧字段。它是一个布尔值,将 ns.dependency 条目标记为部署根。条目 API 从不返回它;registry 所有的状态通过 snap:state() 读取。
获取条目
local entry, err = registry.get("app.lib:assert")
权限: 条目 ID 上的 registry.get
查找条目
local entries, err = registry.find({[".kind"] = "function.lua"})
local entries, err = registry.find({[".kind"] = "http.endpoint", [".ns"] = "app.api"})
以 . 为前缀的键匹配条目字段(.kind、.ns、.name、.id),并接受 * 通配符。以 meta. 为前缀的键匹配条目元数据;meta. 键前再加上 ~、*、^ 或 $ 分别选择正则、包含、前缀或后缀匹配。两种前缀都没有的键会被忽略。
解析 ID
local id = registry.parse_id("app.lib:assert")
-- id.ns = "app.lib", id.name = "assert"
快照
注册表的时间点视图:
local snap, err = registry.snapshot() -- 当前状态
local snap, err = registry.snapshot_at(5) -- 版本 5 时
快照方法
| 方法 | 返回 | 描述 |
|---|---|---|
snap:entries() |
Entry[], error |
所有可访问条目 |
snap:state() |
State, error |
带 registry 所有元数据的条目,以及解析出的模块图 |
snap:get(id) |
Entry, error |
按 ID 获取单个条目 |
snap:find(filter) |
Entry[] |
过滤条目 |
snap:namespace(ns) |
Entry[] |
命名空间中的条目 |
snap:version() |
Version |
快照版本 |
snap:changes() |
Changes |
创建变更集 |
快照状态
snap:state() 返回条目状态以及为该快照版本选定的模块图。registry 所有的来源信息携带在每个条目上,而不是合并进 meta,因此不会与作者编写的元数据混淆。
local snap, err = registry.snapshot()
local state, err = snap:state()
for _, entry in ipairs(state.entries) do
print(entry.id, entry.registry.owner, entry.registry.root)
end
if state.resolution then
print(state.resolution.digest, state.resolution.input_digest)
for _, module in ipairs(state.resolution.modules) do
print(module.name, module.version)
end
end
state.entries 中的每个条目都有那四个面向作者的字段,另加:
registry.owner- 提供该条目的部署来源registry.root- 当条目是部署选中的依赖声明时为true
state.resolution 描述 registry.snapshot() 视图的模块图。在本身不携带依赖图的快照上它不存在,包括 registry.snapshot_at() 和 overlay 快照:
| 字段 | 类型 | 描述 |
|---|---|---|
digest |
string | 完整不可变选择结果的内容摘要 |
input_digest |
string | 已声明根集合的摘要 |
baseline_digest |
string | 求解该图所依据的部署基线的摘要;未绑定时省略 |
roots |
array | 作为求解器输入的、作者编写的依赖声明 |
references |
array | 被折叠到同一组件已有根中的、形如根的声明;为空时省略 |
modules |
array | 选定的模块 |
roots 和 references 中的条目有 id、component 和 version。modules 中的条目有 name 和 version,并在设置时附带 version_id、source、digest、size_bytes 和 protected。
版本
local version, err = registry.current_version()
local versions, err = registry.versions()
print(version:id()) -- 数字 ID
print(version:string()) -- 显示字符串
local prev = version:previous() -- 上一版本或 nil
local next = version:next() -- 下一版本或 nil
历史
local hist, err = registry.history()
local versions, err = hist:versions()
local version, err = hist:get_version(5)
local snap, err = hist:snapshot_at(version)
变更集
构建并应用修改:
local snap, err = registry.snapshot()
local changes = snap:changes()
changes:create({
id = "test:new_entry",
kind = "test.kind",
meta = {type = "test"},
data = {config = "value"}
})
changes:update({
id = "test:existing",
kind = "test.kind",
meta = {updated = true},
data = {new_value = true}
})
changes:delete("test:old_entry")
local new_version, err = changes:apply()
权限: changes:apply() 需要 registry.apply
删除条目
changes:delete() 接受 ID 字符串、带有 id 字符串的表、带有 ns 和 name 字符串的表,或由上述任意形式组成的数组。数组可以嵌套,重复的 ID 会合并为单个删除操作。
changes:delete("test:old_entry")
changes:delete({id = "test:old_entry"})
changes:delete({ns = "test", name = "old_entry"})
changes:delete({"test:a", {ns = "test", name = "b"}, {"test:c"}})
空列表、自引用的表,以及既不是字符串也不是表的值,都会以 errors.INVALID 被拒绝。
Changes 方法
| 方法 | 描述 |
|---|---|
changes:create(entry) |
添加创建操作 |
changes:update(entry) |
添加更新操作 |
changes:delete(id) |
添加删除操作 |
changes:ops() |
获取待处理操作 |
changes:apply() |
应用变更,返回新 Version |
应用版本
回滚或前进到特定版本:
local prev = current_version:previous()
local ok, err = registry.apply_version(prev)
权限: registry.apply_version
构建差异
计算状态转换所需的操作:
local from = {{id = "test:a", kind = "test", meta = {}, data = {}}}
local to = {{id = "test:b", kind = "test", meta = {}, data = {}}}
local ops, err = registry.build_delta(from, to)
for _, op in ipairs(ops) do
print(op.kind, op.entry.id) -- "entry.create"、"entry.update"、"entry.delete"
end
Overlay
Overlay 是由一个逻辑身份拥有的、进程本地的一组 registry 条目。Overlay 条目参与普通的拓扑和 handler 转换,因此服务会像对持久条目一样为它们启动和停止,但它们从不推进 registry 历史,也从不出现在版本中。它们只存在于运行中的进程内,冷启动后为空,因此由所属的控制服务在启动时重新协调。
local snap, err = registry.overlay("data-sources:crm")
返回: Snapshot, error
该快照通过常规方法暴露该所有者的 overlay 条目,并从 snap:version() 报告当前 registry 版本。它还会在打开的那一刻捕获 overlay 世代,这正是写入安全的依据。
local snap, err = registry.overlay("data-sources:crm")
if err then return nil, err end
local changes = snap:changes()
changes:create({
id = "data.crm:connection",
kind = "registry.entry",
meta = {},
data = {endpoint = "https://crm.internal"}
})
local version, err = changes:apply()
在 overlay 快照上调用 changes:apply() 会写入 overlay 并返回当前 registry 版本。不会创建历史版本,因此除非同时发生了持久变更,返回的版本不会改变。
并发
每个 overlay 都带有一个世代计数器,每次成功应用都会递增。只有当世代仍与打开快照时捕获的一致时,changes:apply() 才会成功。对同一 overlay 的并发应用会以标记为可重试的 errors.CONFLICT 失败:重新打开该 overlay 并重建变更集。
local last_err
for _ = 1, 3 do
local snap, err = registry.overlay("data-sources:crm")
if err then return nil, err end
local _, apply_err = snap:changes():delete("data.crm:connection"):apply()
if not apply_err then return true end
if not apply_err:retryable() then return nil, apply_err end
last_err = apply_err
end
return nil, last_err
限制
- 所有者字符串为必填项,且不能为空白。
- 变更集必须非空,且不得两次指定同一条目。
- 当 ID 已存在于持久状态或任何 overlay 中时,
create会失败。 update和delete只能作用于该所有者创建的条目;任何其他 ID 都会以errors.NOT_FOUND失败。- Overlay 条目不能设置
dependency_root或任何其他 registry 所有的元数据。 - Overlay 条目不能使用被 registry 指令占用的类型,例如
ns.dependency。 - 移除仍有存续条目依赖的条目的删除操作会被拒绝。
- 依赖不能跨越 overlay 所有者边界,持久条目也不能依赖 overlay 条目。
其余的都表现为 errors.CONFLICT 或 errors.INVALID,且都不可重试:只有上面的世代不匹配可以重试。
权限: 打开和读取需要该所有者上的 registry.overlay.get,写入需要该所有者上的 registry.overlay.apply,以及变更集中每个条目 ID 上的 registry.overlay.<create|update|delete>.<kind>。
权限
| 权限 | 资源 | 描述 |
|---|---|---|
registry.get |
条目 ID | 读取条目(也过滤 find/entries 结果) |
registry.apply |
- | 应用变更集 |
registry.apply_version |
- | 应用/回滚版本 |
registry.overlay.get |
所有者 ID | 打开并读取 overlay 快照 |
registry.overlay.apply |
所有者 ID | 应用 overlay 变更集 |
registry.overlay.create.<kind> |
条目 ID | 创建该类型的 overlay 条目 |
registry.overlay.update.<kind> |
条目 ID | 更新该类型的 overlay 条目 |
registry.overlay.delete.<kind> |
条目 ID | 删除该类型的 overlay 条目 |
错误
| 条件 | 类型 |
|---|---|
| 条目未找到 | errors.NOT_FOUND |
| 版本未找到 | errors.NOT_FOUND |
| 权限被拒绝 | errors.PERMISSION_DENIED |
| 无效参数 | errors.INVALID |
| 无变更可应用 | errors.INVALID |
| 应用期间 overlay 发生变更 | errors.CONFLICT(可重试) |
| Overlay 条目归属他处或与持久状态冲突 | errors.CONFLICT |
| 注册表不可用 | errors.INTERNAL |
参见 错误处理 了解错误处理方法。