Skip to main content

Registry

Struct Registry 

Source
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

Source

pub fn new() -> Self

Examples found in repository?
examples/quickstart.rs (line 16)
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, &params, &registry, 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, &registry)?;
47        println!("sql        = {}", serde_json::to_string(&sql).unwrap());
48    }
49
50    Ok(())
51}
Source

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 运行期新注册不做承诺)。

Source

pub fn is_view(&self) -> bool

是否派生视图(false = base 目录唯一真源)

Source

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?
examples/quickstart.rs (lines 17-27)
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, &params, &registry, 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, &registry)?;
47        println!("sql        = {}", serde_json::to_string(&sql).unwrap());
48    }
49
50    Ok(())
51}
Source

pub fn register_with_ctx( &mut self, defn: &Value, ctx: Option<&Context>, ) -> Result<(), String>

带 ctx 的注册(单条 + 缺省落点):内部转 Self::register_batch。

Source

pub fn register_batch( &mut self, items: &[(Value, Location)], ctx: Option<&Context>, ) -> Result<(), String>

带定位的批量注册(D13:唯一性校验落「装载批次集合」)。

算法(先构造后落库,任一步 Err ⇒ 零副作用):

  1. 判据单点 [classify_batch](分组 / 主唯一 ≥2 ⇒ Err / 批内四元组冲突),与 schema::load::plan_load 同源。
  2. can_register 门禁(判决先于 build_schema)。
  3. 逐组:有主 ⇒ build_schema 为 主;0 主 ⇒ 追加既有同名 entry 的从链路,无既有 ⇒ Err。
  4. 全批 + 既有 (source, database, schema, collection) 跨名冲突 ⇒ Err (判据函数 [detect_location_conflict],替代旧 check_location_unique)。
  5. 提交:links = [primary.loc] ++ replicas;命中既有 entry ⇒ version + 1 (order 位置不变)、替换结构与链路;新名 ⇒ version = 1、order.push。 Schema.source/database/schema 由 primary.loc 注入(source == "default" ⇒ None)。
  6. 归档派生:主 name 不以 "Deleted" 结尾且非 _isArchive ⇒ 派生 <Name>Deleted (links 继承主链路,定位同主)。

把 config.links 的角色/优先级附着到各 entry 的链路集;声明但缺失的链路按声明序补建。

算法(先校验后落库,任一 Err ⇒ 零副作用,与 Self::register_batch 同规):

  1. 逐项取 Self::get_entry(未注册 ⇒ Err,禁猜——该名可能由其它批次注册)。
  2. 每条声明按 Location::same_place 在 entry.links 中匹配来源(只比三元组): 命中 ⇒ 写回 role/priority;未命中 ⇒ 按声明序追加 Location。
  3. 归档随附表 <Name>Deleted(若已注册且未在 links 中独立声明)继承主的重算链路。
  4. 未在 cfg.links 中出现的 entry / 链路:保持原样(零回归);links 为空 ⇒ no-op。

主链路 + 从链路(只读)

读链路解析:排序(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, 本函数不重复该判据。

Source

pub fn primary_location(&self, name: &str) -> Result<&Location, String>

主落点(= links[0])

Source

pub fn version_of(&self, name: &str) -> Result<u64, String>

版本(首次 = 1)

Source

pub fn get(&self, name: &str) -> Result<&Schema, String>

按名称获取 schema

Source

pub fn has(&self, name: &str) -> bool

Source

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),守卫仍显式、不静默。

Source

pub fn set_require_context(&mut self, require: bool)

开关「上下文强制」(默认关闭 = fail-open,保持 JS parity)。 开启后:plan 入口遇 ctx: None 报 ERR_NO_CONTEXT(fail-secure)。 内部调用须显式传系统上下文({"internal": true})。

Source

pub fn require_context(&self) -> bool

「上下文强制」开关当前值

Source

pub fn set_profile(&mut self, profile: Profile)

设置查询档位(standard / text2query)。

档位为单值状态(非栈):由 Host 的 text2query() 上下文管理器负责 进入时设档、退出时恢复(见 py-store / nodejs-store 门面)。判决一律在 core。

Source

pub fn profile(&self) -> Profile

当前查询档位

Source

pub fn set_exempt_roles(&mut self, roles: Vec<String>)

豁免角色清单:命中者在一切判决环节(静态 + RBAC)直接放行。默认空——无豁免。

Source

pub fn set_deny_write_roles(&mut self, roles: Vec<String>)

拒写角色清单:命中者一切写路径拒绝(读不受影响)。默认空——无拒写。

Source

pub fn set_unconfigured_policy(&mut self, policy: UnconfiguredPolicy)

schema 白名单缺失/为空时的默认姿态。默认 Open(保持现状语义)。

Source

pub fn role_rules(&self) -> &RoleRules

当前角色规则(静态判决函数与 RBAC decide 的共用取参入口)

Source

pub fn set_meta_policy(&mut self, closed: bool, roles: Vec<String>)

定义层门禁策略(closed=true 时仅 internal 或 roles 白名单可注册/覆盖)。 默认 Open —— 全放行(保持既有 parity;须在首次业务注册前调用方生效于该次注册)。

Source

pub fn meta_policy(&self) -> &MetaPolicy

当前定义层门禁策略

设置跨连接写策略(默认 WriteLinkPolicy::Reject)。

判决唯一在 core([crate::command::write_links::resolve_write_links]); 宿主仅需在初始化期把它透传到 registry。

当前跨连接写策略

Source

pub fn can_register(&self, ctx: Option<&Context>) -> bool

只读定义层判决(workflow 等宿主侧定义面复用同一门禁;判决唯一在 core)。

不改变任何注册状态:Open 全放行;Closed 仅 internal 或 roles 白名单角色。 语义与 Self::register_with_ctx 的门禁判据完全一致(同一 can_register),仅作只读暴露。

Source

pub fn set_rbac(&mut self, policy: Option<&Value>) -> Result<(), String>

注入/清除 RBAC 动态策略;None = 关闭(判决原语直通)。 解析失败 Err(fail-fast,禁静默吞配置错误),成功后判决链路即刻生效。

Source

pub fn rbac(&self) -> Option<&RbacPolicy>

当前 RBAC 策略(None = 未启用)

Source

pub fn get_by_location( &self, source: &str, database: Option<&str>, schema: Option<&str>, collection: &str, ) -> Result<&Schema, String>

按定位四元组精确获取 schema(命令路由的唯一定位入口)

命中判据:collection 相等 且 四元组命中该 entry 的任一链路。 不做任何猜测回落。

Source

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)。

Source

pub fn list(&self) -> Vec<String>

Source

pub fn schema_datasource(&self, name: &str) -> Result<Option<String>, String>

schema 绑定的数据源名(= 主链路 source;default → None)

Source

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。

Trait Implementations§

Source§

impl Clone for Registry

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Registry

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Registry

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.