pub struct Registry { /* private fields */ }Expand description
Schema 注册表:共享目录快照(Arc<Catalog>)+ 策略束(PolicyBundle)。
is_base = true:目录唯一真源,注册 / 清空写路径仅在此开放;- 派生视图(
with_policy产出)持同一Arc<Catalog>快照 + 叠加策略,is_base = false。
Implementations§
Source§impl Registry
impl Registry
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
14fn main() -> Result<(), String> {
15 // 1. A model is plain JSON — defined once, usable against every backend.
16 let mut registry = Registry::new();
17 registry.register(&json!({
18 "name": "Post",
19 "collection": "posts",
20 "timestamps": true,
21 "fields": {
22 "title": { "type": "string" },
23 "status": { "type": "string", "default": "draft" },
24 "views": { "type": "int" }
25 },
26 "relations": {}
27 }))?;
28
29 // 2. GQL in, MongoDB command JSON out. Values are referenced by `@key`.
30 let gql = "Post($condition:@c0,$sort:@s1,$limit:@l0){title, status, views}";
31 let mut params = Map::new();
32 params.insert("c0".to_string(), json!({ "status": "published" }));
33 params.insert("s1".to_string(), json!({ "views": -1 }));
34 params.insert("l0".to_string(), json!(20));
35
36 let plan = plan_query(gql, ¶ms, ®istry, None)?;
37
38 println!("collection = {}", plan.collection);
39 println!("mode = {}", plan.mode.as_str());
40
41 for cmd in &plan.commands {
42 println!("command = {}", serde_json::to_string(cmd).unwrap());
43
44 // 3. The host runs `cmd` against MongoDB — or, for a SQL backend, asks the
45 // core for parameterized SQL and binds it with its own driver.
46 let sql = translate(Backend::Postgres, cmd, ®istry)?;
47 println!("sql = {}", serde_json::to_string(&sql).unwrap());
48 }
49
50 Ok(())
51}Sourcepub fn with_policy(&self, overrides: &PolicyOverrides) -> Registry
pub fn with_policy(&self, overrides: &PolicyOverrides) -> Registry
派生策略视图(O(1)):共享目录快照 Arc<Catalog> + 叠加策略覆盖;派生视图 is_base = false。
快照语义:视图持派生时点目录,base 后续注册经 Arc::make_mut 写时复制,对后续派生
视图即时可见,对在途视图不承诺(与 S2 现状口径一致:store-api/spec/01-routing.md 运行期新注册不做承诺)。
Sourcepub fn register(&mut self, defn: &Value) -> Result<(), String>
pub fn register(&mut self, defn: &Value) -> Result<(), String>
注册一个 schema(含自动注册 <Name>Deleted 归档表),对应 JS register。
兼容入口:单条 + 缺省落点(source="default"、database/schema=None)。
定义层门禁按当前 MetaPolicy 判决
(默认 Open → 全放行)。需带 ctx 显式过门禁请用 Self::register_with_ctx。
Examples found in repository?
14fn main() -> Result<(), String> {
15 // 1. A model is plain JSON — defined once, usable against every backend.
16 let mut registry = Registry::new();
17 registry.register(&json!({
18 "name": "Post",
19 "collection": "posts",
20 "timestamps": true,
21 "fields": {
22 "title": { "type": "string" },
23 "status": { "type": "string", "default": "draft" },
24 "views": { "type": "int" }
25 },
26 "relations": {}
27 }))?;
28
29 // 2. GQL in, MongoDB command JSON out. Values are referenced by `@key`.
30 let gql = "Post($condition:@c0,$sort:@s1,$limit:@l0){title, status, views}";
31 let mut params = Map::new();
32 params.insert("c0".to_string(), json!({ "status": "published" }));
33 params.insert("s1".to_string(), json!({ "views": -1 }));
34 params.insert("l0".to_string(), json!(20));
35
36 let plan = plan_query(gql, ¶ms, ®istry, None)?;
37
38 println!("collection = {}", plan.collection);
39 println!("mode = {}", plan.mode.as_str());
40
41 for cmd in &plan.commands {
42 println!("command = {}", serde_json::to_string(cmd).unwrap());
43
44 // 3. The host runs `cmd` against MongoDB — or, for a SQL backend, asks the
45 // core for parameterized SQL and binds it with its own driver.
46 let sql = translate(Backend::Postgres, cmd, ®istry)?;
47 println!("sql = {}", serde_json::to_string(&sql).unwrap());
48 }
49
50 Ok(())
51}Sourcepub fn register_with_ctx(
&mut self,
defn: &Value,
ctx: Option<&Context>,
) -> Result<(), String>
pub fn register_with_ctx( &mut self, defn: &Value, ctx: Option<&Context>, ) -> Result<(), String>
带 ctx 的注册(单条 + 缺省落点):内部转 Self::register_batch。
Sourcepub fn register_batch(
&mut self,
items: &[(Value, Location)],
ctx: Option<&Context>,
) -> Result<(), String>
pub fn register_batch( &mut self, items: &[(Value, Location)], ctx: Option<&Context>, ) -> Result<(), String>
带定位的批量注册(D13:唯一性校验落「装载批次集合」)。
算法(先构造后落库,任一步 Err ⇒ 零副作用):
- 判据单点 [
classify_batch](分组 / 主唯一 ≥2 ⇒Err/ 批内四元组冲突),与schema::load::plan_load同源。 can_register门禁(判决先于build_schema)。- 逐组:有主 ⇒
build_schema为 主;0 主 ⇒ 追加既有同名 entry 的从链路,无既有 ⇒Err。 - 全批 + 既有
(source, database, schema, collection)跨名冲突 ⇒Err(判据函数 [detect_location_conflict],替代旧check_location_unique)。 - 提交:
links = [primary.loc] ++ replicas;命中既有 entry ⇒version + 1(order位置不变)、替换结构与链路;新名 ⇒version = 1、order.push。Schema.source/database/schema由primary.loc注入(source == "default"⇒None)。 - 归档派生:主
name不以"Deleted"结尾且非_isArchive⇒ 派生<Name>Deleted(links继承主链路,定位同主)。
Sourcepub fn apply_link_decls(&mut self, cfg: &LoadConfig) -> Result<(), String>
pub fn apply_link_decls(&mut self, cfg: &LoadConfig) -> Result<(), String>
把 config.links 的角色/优先级附着到各 entry 的链路集;声明但缺失的链路按声明序补建。
算法(先校验后落库,任一 Err ⇒ 零副作用,与 Self::register_batch 同规):
- 逐项取
Self::get_entry(未注册 ⇒Err,禁猜——该名可能由其它批次注册)。 - 每条声明按
Location::same_place在entry.links中匹配来源(只比三元组): 命中 ⇒ 写回role/priority;未命中 ⇒ 按声明序追加Location。 - 归档随附表
<Name>Deleted(若已注册且未在links中独立声明)继承主的重算链路。 - 未在
cfg.links中出现的 entry / 链路:保持原样(零回归);links为空 ⇒ no-op。
Sourcepub fn resolve_read_links(
&self,
name: &str,
unreachable: Option<&[String]>,
) -> Result<ReadLinks, String>
pub fn resolve_read_links( &self, name: &str, unreachable: Option<&[String]>, ) -> Result<ReadLinks, String>
读链路解析:排序(role → priority → 声明序)+ 跳过不可达 + 产降级声明。
排序用稳定 sort_by_key:键为 (role.map_or(4u8, |r| r.rank()), priority.unwrap_or(i64::MAX))
——未声明 role 视作最低层(4)、未声明 priority 视作最大;稳定排序 ⇒ 同级保声明序,
无任何 links 声明时全为 (4, MAX) ⇒ 顺序 = 原序(零回归)。
unreachable:本次调用不可达的 source 列表(由 Host 下发;None = 不限制);
命中某链路 source ⇒ 从结果剔除并 push 降级声明(禁静默)。全部链路被跳过 ⇒
Err:ERR_READ_NO_REACHABLE_LINK: <name>(绝不回落主链路)。
links[0] 即读路径的选中落点(替代 primary_location 在读路径的角色;
primary_location 保留供写路径与兼容入口)。可达过滤判据单点在
federation::plan::select::filter_reachable,
本函数不重复该判据。
pub fn has(&self, name: &str) -> bool
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
清空 schema 注册表(schemas + order),对应绑定层的测试隔离 / 动态重建场景。
只清 schema,不动配置开关(require_context / profile / rbac /
role_rules)与回调表(clear_fns 对称:各清各的)——开关生命周期属
Registry 配置面,不随 schema 集合重建而丢。
非 base 视图调用即 panic!(消息携带 ERR_POLICY_VIEW_READONLY 前缀)——
本方法返回 ()(受「core 公开签名零改动」约束,无法回 Result),守卫仍显式、不静默。
Sourcepub fn set_require_context(&mut self, require: bool)
pub fn set_require_context(&mut self, require: bool)
开关「上下文强制」(默认关闭 = fail-open,保持 JS parity)。
开启后:plan 入口遇 ctx: None 报 ERR_NO_CONTEXT(fail-secure)。
内部调用须显式传系统上下文({"internal": true})。
Sourcepub fn require_context(&self) -> bool
pub fn require_context(&self) -> bool
「上下文强制」开关当前值
Sourcepub fn set_profile(&mut self, profile: Profile)
pub fn set_profile(&mut self, profile: Profile)
设置查询档位(standard / text2query)。
档位为单值状态(非栈):由 Host 的 text2query() 上下文管理器负责
进入时设档、退出时恢复(见 py-store / nodejs-store 门面)。判决一律在 core。
Sourcepub fn set_exempt_roles(&mut self, roles: Vec<String>)
pub fn set_exempt_roles(&mut self, roles: Vec<String>)
豁免角色清单:命中者在一切判决环节(静态 + RBAC)直接放行。默认空——无豁免。
Sourcepub fn set_deny_write_roles(&mut self, roles: Vec<String>)
pub fn set_deny_write_roles(&mut self, roles: Vec<String>)
拒写角色清单:命中者一切写路径拒绝(读不受影响)。默认空——无拒写。
Sourcepub fn set_unconfigured_policy(&mut self, policy: UnconfiguredPolicy)
pub fn set_unconfigured_policy(&mut self, policy: UnconfiguredPolicy)
schema 白名单缺失/为空时的默认姿态。默认 Open(保持现状语义)。
Sourcepub fn role_rules(&self) -> &RoleRules
pub fn role_rules(&self) -> &RoleRules
当前角色规则(静态判决函数与 RBAC decide 的共用取参入口)
Sourcepub fn set_meta_policy(&mut self, closed: bool, roles: Vec<String>)
pub fn set_meta_policy(&mut self, closed: bool, roles: Vec<String>)
定义层门禁策略(closed=true 时仅 internal 或 roles 白名单可注册/覆盖)。
默认 Open —— 全放行(保持既有 parity;须在首次业务注册前调用方生效于该次注册)。
Sourcepub fn meta_policy(&self) -> &MetaPolicy
pub fn meta_policy(&self) -> &MetaPolicy
当前定义层门禁策略
Sourcepub fn set_write_link_policy(&mut self, policy: WriteLinkPolicy)
pub fn set_write_link_policy(&mut self, policy: WriteLinkPolicy)
设置跨连接写策略(默认 WriteLinkPolicy::Reject)。
判决唯一在 core([crate::command::write_links::resolve_write_links]);
宿主仅需在初始化期把它透传到 registry。
Sourcepub fn write_link_policy(&self) -> WriteLinkPolicy
pub fn write_link_policy(&self) -> WriteLinkPolicy
当前跨连接写策略
Sourcepub fn can_register(&self, ctx: Option<&Context>) -> bool
pub fn can_register(&self, ctx: Option<&Context>) -> bool
只读定义层判决(workflow 等宿主侧定义面复用同一门禁;判决唯一在 core)。
不改变任何注册状态:Open 全放行;Closed 仅 internal 或 roles 白名单角色。
语义与 Self::register_with_ctx 的门禁判据完全一致(同一
can_register),仅作只读暴露。
Sourcepub fn set_rbac(&mut self, policy: Option<&Value>) -> Result<(), String>
pub fn set_rbac(&mut self, policy: Option<&Value>) -> Result<(), String>
注入/清除 RBAC 动态策略;None = 关闭(判决原语直通)。
解析失败 Err(fail-fast,禁静默吞配置错误),成功后判决链路即刻生效。
Sourcepub fn rbac(&self) -> Option<&RbacPolicy>
pub fn rbac(&self) -> Option<&RbacPolicy>
当前 RBAC 策略(None = 未启用)
Sourcepub fn get_by_location(
&self,
source: &str,
database: Option<&str>,
schema: Option<&str>,
collection: &str,
) -> Result<&Schema, String>
pub fn get_by_location( &self, source: &str, database: Option<&str>, schema: Option<&str>, collection: &str, ) -> Result<&Schema, String>
按定位四元组精确获取 schema(命令路由的唯一定位入口)
命中判据:collection 相等 且 四元组命中该 entry 的任一链路。
不做任何猜测回落。
Sourcepub fn get_for_command(
&self,
source: &str,
database: Option<&str>,
schema: Option<&str>,
collection: &str,
) -> Result<&Schema, String>
pub fn get_for_command( &self, source: &str, database: Option<&str>, schema: Option<&str>, collection: &str, ) -> Result<&Schema, String>
命令结构定位(方言翻译用):优先四元组精确命中;未命中时(route_override
改写落点的多租户场景)回落 (source, collection) 定位 —— 结构 schema
与定位落点正交(见 multi-datasource-routing-plan.md §6:权限/字段校验仍按结构 schema)。
(source, collection) 恰一候选 → 命中;多候选时取 database/schema 均 null 的
结构声明,无该声明 → 报错(拒绝猜测,铁律 3)。
pub fn list(&self) -> Vec<String>
Sourcepub fn schema_datasource(&self, name: &str) -> Result<Option<String>, String>
pub fn schema_datasource(&self, name: &str) -> Result<Option<String>, String>
schema 绑定的数据源名(= 主链路 source;default → None)
Sourcepub fn resolve_datasource(
&self,
schema_name: &str,
config: &Value,
) -> Result<DataSource, String>
pub fn resolve_datasource( &self, schema_name: &str, config: &Value, ) -> Result<DataSource, String>
解析 schema 绑定的数据源(config 为 { "sources": { name: kind } })
纯逻辑:不持有连接(连接句柄留在 Host)。null / 空配置下等价单源 Mongo,
保证既有调用方与 parity fixture 零变更。见 crate::datasource。