docs(session): align projection hint ordering
This commit is contained in:
parent
b2071a50b9
commit
b36f3d323a
8 changed files with 26 additions and 25 deletions
|
|
@ -2,5 +2,5 @@
|
||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||||
# after editing either side, bring the other along and re-record with:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/subsystems/session-projection.md
|
# pnpm run verify-translation-pairing --write docs/subsystems/session-projection.md
|
||||||
session-projection.md: ba4040e9692c4b3453b1e134a8f0654e59d51c79
|
session-projection.md: 87a11475bd12ed922030f08ae5d164641b95ec09
|
||||||
session-projection.zh.md: 7a190c586efdd44dcd659a65164b5b0a43dbe002
|
session-projection.zh.md: 7af0cfc7e9eba696d3bf826de6b0e4067a245aaf
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,11 @@ The persisted projection cache service. Opens the `session_projcache` domain at
|
||||||
```ts cordis-catalog
|
```ts cordis-catalog
|
||||||
/**
|
/**
|
||||||
* The zero-I/O listing read: whole values viewed straight from the stored
|
* The zero-I/O listing read: whole values viewed straight from the stored
|
||||||
* rows (version-matching keys only), each cut carried with its watermark so
|
* rows (version-matching keys only), with the lowest served watermark carried
|
||||||
* a client value store can apply the same higher-seq-wins rule used for all
|
* for later authoritative reconciliation. The caller's header keeps unrelated
|
||||||
* projection sources. The caller's header keeps unrelated lifecycles out;
|
* lifecycles out; repeated list blocks are arrival-ordered tentative hints
|
||||||
* the value remains a best-effort cached observation until a fresher cut
|
* because crash repair may lower the durable sequence; authoritative frames
|
||||||
* arrives.
|
* replace matching rows, and complete baselines replace the full set.
|
||||||
* @param meta - the listed session's header (identity witness; no log read).
|
* @param meta - the listed session's header (identity witness; no log read).
|
||||||
* @param keys - optional projection keys required by the caller's audience.
|
* @param keys - optional projection keys required by the caller's audience.
|
||||||
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
||||||
|
|
|
||||||
|
|
@ -118,11 +118,11 @@ The persisted projection cache service. Opens the `session_projcache` domain at
|
||||||
```ts cordis-catalog
|
```ts cordis-catalog
|
||||||
/**
|
/**
|
||||||
* The zero-I/O listing read: whole values viewed straight from the stored
|
* The zero-I/O listing read: whole values viewed straight from the stored
|
||||||
* rows (version-matching keys only), each cut carried with its watermark so
|
* rows (version-matching keys only), with the lowest served watermark carried
|
||||||
* a client value store can apply the same higher-seq-wins rule used for all
|
* for later authoritative reconciliation. The caller's header keeps unrelated
|
||||||
* projection sources. The caller's header keeps unrelated lifecycles out;
|
* lifecycles out; repeated list blocks are arrival-ordered tentative hints
|
||||||
* the value remains a best-effort cached observation until a fresher cut
|
* because crash repair may lower the durable sequence; authoritative frames
|
||||||
* arrives.
|
* replace matching rows, and complete baselines replace the full set.
|
||||||
* @param meta - the listed session's header (identity witness; no log read).
|
* @param meta - the listed session's header (identity witness; no log read).
|
||||||
* @param keys - optional projection keys required by the caller's audience.
|
* @param keys - optional projection keys required by the caller's audience.
|
||||||
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
||||||
|
|
|
||||||
|
|
@ -1503,7 +1503,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
|
||||||
methods: [
|
methods: [
|
||||||
{
|
{
|
||||||
signature: 'cachedSnapshot( meta: SessionHeader, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined',
|
signature: 'cachedSnapshot( meta: SessionHeader, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined',
|
||||||
description: 'The zero-I/O listing read: whole values viewed straight from the stored rows (version-matching keys only), each cut carried with its watermark so a client value store can apply the same higher-seq-wins rule used for all projection sources. The caller\'s header keeps unrelated lifecycles out; the value remains a best-effort cached observation until a fresher cut arrives.',
|
description: 'The zero-I/O listing read: whole values viewed straight from the stored rows (version-matching keys only), with the lowest served watermark carried for later authoritative reconciliation. The caller\'s header keeps unrelated lifecycles out; repeated list blocks are arrival-ordered tentative hints because crash repair may lower the durable sequence; authoritative frames replace matching rows, and complete baselines replace the full set.',
|
||||||
parameters: [{ name: 'meta', description: 'the listed session\'s header (identity witness; no log read).' }, { name: 'keys', description: 'optional projection keys required by the caller\'s audience.' }],
|
parameters: [{ name: 'meta', description: 'the listed session\'s header (identity witness; no log read).' }, { name: 'keys', description: 'optional projection keys required by the caller\'s audience.' }],
|
||||||
returns: 'the cut (`asOfSeq` = lowest served-row watermark), or `undefined` when no usable row exists for this lifecycle.',
|
returns: 'the cut (`asOfSeq` = lowest served-row watermark), or `undefined` when no usable row exists for this lifecycle.',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||||
# after editing either side, bring the other along and re-record with:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write packages/session/session-projection-cache/README.md
|
# pnpm run verify-translation-pairing --write packages/session/session-projection-cache/README.md
|
||||||
README.md: 9d1619fe25075577218e95a843f752ce3cec7cfb
|
README.md: 24ca9abb3ea4403331f37b60cbd83374398cd54d
|
||||||
README.zh.md: cd72f124865df32b8576d7f6dd3aff12a3a1cd05
|
README.zh.md: 3bca8ac80ca2e0488cfa8fada9b023505810d09e
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ Three mandatory points always write: session creation persists the seed-derived
|
||||||
|
|
||||||
### Reading cached values
|
### Reading cached values
|
||||||
|
|
||||||
`cachedSnapshot(meta)` synchronously serves client values from the storage domain's coherent in-memory table with zero I/O. It accepts only an identity-matching record and version- and schema-matching client keys, then returns a best-effort `{ asOfSeq, values }` cut at the lowest served-row watermark; host-only rows are omitted. It returns `undefined` for an unknown id, unrelated lifecycle, absent or foreign record document, or no usable rows. The list carrier submits this value as a tentative hint to the per-Session Client projection store. Higher-sequence hints replace earlier tentative rows; the first authoritative frame replaces a tentative row regardless of sequence, and later frames require a higher sequence. A successful follow opening gives the store a complete cut: it replaces pre-opening rows and retains only authoritative frames that arrived after the opening began and are newer than that cut. A control-generation baseline also replaces its complete per-Session value, including equal-sequence and omitted keys; when it arrives during an opening at an equal or newer cut, it remains authoritative.
|
`cachedSnapshot(meta)` synchronously serves client values from the storage domain's coherent in-memory table with zero I/O. It accepts only an identity-matching record and version- and schema-matching client keys, then returns a best-effort `{ asOfSeq, values }` cut at the lowest served-row watermark; host-only rows are omitted. It returns `undefined` for an unknown id, unrelated lifecycle, absent or foreign record document, or no usable rows. The list carrier submits this value as a tentative hint to the per-Session Client projection store. For each carried key, a later list block replaces an earlier tentative row by arrival order, even when crash repair lowers its durable watermark; the first authoritative frame replaces a tentative row regardless of sequence, and later frames require a higher sequence. A successful follow opening gives the store a complete cut: it replaces pre-opening rows and retains only authoritative frames that arrived after the opening began and are newer than that cut. A control-generation baseline also replaces its complete per-Session value, including equal-sequence and omitted keys; when it arrives during an opening at an equal or newer cut, it remains authoritative.
|
||||||
|
|
||||||
`coldSnapshot(meta, events)` accepts the complete ordered log, validates every seeded row against that exact extent once, folds any required events from `init(header)`, and refreshes the record without consulting persistence. `hydratePrepared(session, meta, events)` performs the production exact-read validation for an unpublished prepared Session; if cached state is malformed or out of range, that path retries over the full supplied log from `init(header)`. Corruption in the durable event stream still fails the retry instead of producing a partial snapshot.
|
`coldSnapshot(meta, events)` accepts the complete ordered log, validates every seeded row against that exact extent once, folds any required events from `init(header)`, and refreshes the record without consulting persistence. `hydratePrepared(session, meta, events)` performs the production exact-read validation for an unpublished prepared Session; if cached state is malformed or out of range, that path retries over the full supplied log from `init(header)`. Corruption in the durable event stream still fails the retry instead of producing a partial snapshot.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ kind: "package-reference"
|
||||||
|
|
||||||
### 读取缓存值
|
### 读取缓存值
|
||||||
|
|
||||||
`cachedSnapshot(meta)` 以零 I/O 从存储域一致的内存表同步提供客户端值。它只接受身份匹配的记录及版本和 schema 均匹配的客户端 key,再按所服务行的最低水位返回尽力而为的 `{ asOfSeq, values }` 切面;host-only 行会被省略。对于未知 id、无关生命周期、缺失或外来的记录文档,或没有可用行的情况,它返回 `undefined`。列表载体把该值作为暂定 hint 交给逐 Session 的 Client projection store。较高 sequence 的 hint 会替换较早的暂定 row;首个权威 frame 无论 sequence 如何都会替换暂定 row,后续 frame 则必须具有更高 sequence。成功的 follow opening 为 store 提供一份完整 cut:它替换 opening 前的 row,只保留 opening 开始后到达且新于该 cut 的权威 frame。control generation baseline 也会精确替换该 Session 的完整值,包括等 sequence row 与缺失 key;若它在 opening 期间以等于或新于 opening cut 的 cut 到达,它保持权威。
|
`cachedSnapshot(meta)` 以零 I/O 从存储域一致的内存表同步提供客户端值。它只接受身份匹配的记录及版本和 schema 均匹配的客户端 key,再按所服务行的最低水位返回尽力而为的 `{ asOfSeq, values }` 切面;host-only 行会被省略。对于未知 id、无关生命周期、缺失或外来的记录文档,或没有可用行的情况,它返回 `undefined`。列表载体把该值作为暂定 hint 交给逐 Session 的 Client projection store。对于每个携带的 key,后到的列表 block 按到达顺序替换先前的暂定 row,即使崩溃修复使其持久水位降低;首个权威 frame 无论 sequence 如何都会替换暂定 row,后续 frame 则必须具有更高 sequence。成功的 follow opening 为 store 提供一份完整 cut:它替换 opening 前的 row,只保留 opening 开始后到达且新于该 cut 的权威 frame。control generation baseline 也会精确替换该 Session 的完整值,包括等 sequence row 与缺失 key;若它在 opening 期间以等于或新于 opening cut 的 cut 到达,它保持权威。
|
||||||
|
|
||||||
`coldSnapshot(meta, events)` 接受完整有序日志,只以该精确范围校验一次每条 seed row,从 `init(header)` 折叠所需事件,并在不访问持久化层的情况下刷新记录。`hydratePrepared(session, meta, events)` 为尚未发布的 prepared Session 执行生产精确读取校验;若缓存状态畸形或越界,只有该路径会在所提供的完整日志上从 `init(header)` 重试。持久事件流本身若已损坏,重试仍然失败,绝不会产出部分快照。
|
`coldSnapshot(meta, events)` 接受完整有序日志,只以该精确范围校验一次每条 seed row,从 `init(header)` 折叠所需事件,并在不访问持久化层的情况下刷新记录。`hydratePrepared(session, meta, events)` 为尚未发布的 prepared Session 执行生产精确读取校验;若缓存状态畸形或越界,只有该路径会在所提供的完整日志上从 `init(header)` 重试。持久事件流本身若已损坏,重试仍然失败,绝不会产出部分快照。
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,11 +111,11 @@ export class SessionProjectionCache extends Service {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The zero-I/O listing read: whole values viewed straight from the stored
|
* The zero-I/O listing read: whole values viewed straight from the stored
|
||||||
* rows (version-matching keys only), each cut carried with its watermark so
|
* rows (version-matching keys only), with the lowest served watermark carried
|
||||||
* a client value store can apply the same higher-seq-wins rule used for all
|
* for later authoritative reconciliation. The caller's header keeps unrelated
|
||||||
* projection sources. The caller's header keeps unrelated lifecycles out;
|
* lifecycles out; repeated list blocks are arrival-ordered tentative hints
|
||||||
* the value remains a best-effort cached observation until a fresher cut
|
* because crash repair may lower the durable sequence; authoritative frames
|
||||||
* arrives.
|
* replace matching rows, and complete baselines replace the full set.
|
||||||
* @param meta - the listed session's header (identity witness; no log read).
|
* @param meta - the listed session's header (identity witness; no log read).
|
||||||
* @param keys - optional projection keys required by the caller's audience.
|
* @param keys - optional projection keys required by the caller's audience.
|
||||||
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
* @returns the cut (`asOfSeq` = lowest served-row watermark), or
|
||||||
|
|
@ -130,9 +130,10 @@ export class SessionProjectionCache extends Service {
|
||||||
const values = this.ctx.sessionProjections.viewCheckpoint(record.rows, keys)
|
const values = this.ctx.sessionProjections.viewCheckpoint(record.rows, keys)
|
||||||
const servedKeys = Object.keys(values)
|
const servedKeys = Object.keys(values)
|
||||||
if (servedKeys.length === 0) return undefined
|
if (servedKeys.length === 0) return undefined
|
||||||
// The block carries ONE cut: the lowest served watermark is the seq every
|
// The block carries ONE cut: the lowest served watermark is the sequence
|
||||||
// value is at least current as of. Under-claiming is safe under
|
// through which every value is known current. The Client orders tentative
|
||||||
// higher-seq-wins; over-claiming could outrank a fresher observation.
|
// list blocks by arrival so a crash-repaired lower watermark can replace an
|
||||||
|
// older hint; authoritative frames and baselines own later reconciliation.
|
||||||
const asOfSeq = Math.min(...servedKeys.map(key => (record.rows[key] as { seq: number }).seq))
|
const asOfSeq = Math.min(...servedKeys.map(key => (record.rows[key] as { seq: number }).seq))
|
||||||
return { asOfSeq, values }
|
return { asOfSeq, values }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue