feat(transaction): expose structured participant registration
This commit is contained in:
parent
469bdff17d
commit
25cb66c040
@ -13,6 +13,8 @@ All notable changes to the tp library are documented here.
|
|||||||
- `tp-runtime-manifest`, advertising `tp-transaction-protocol-v1+v2` without removing the v1 participant route.
|
- `tp-runtime-manifest`, advertising `tp-transaction-protocol-v1+v2` without removing the v1 participant route.
|
||||||
- Supported `tp-transaction-execution-route` kill switch with `structured` as
|
- Supported `tp-transaction-execution-route` kill switch with `structured` as
|
||||||
the default live authority and `v1` as the complete legacy rollback route.
|
the default live authority and `v1` as the complete legacy rollback route.
|
||||||
|
- Public `tp-transaction-participate-v2` registration for cross-package
|
||||||
|
structured participants, with the v1 call-shape adapter retained unchanged.
|
||||||
- Native property policies and contribution composition with explicit nil/absence, normalization, validation, equality, merge, projection, named direct styles, and explicit `tp-computed` value sources.
|
- Native property policies and contribution composition with explicit nil/absence, normalization, validation, equality, merge, projection, named direct styles, and explicit `tp-computed` value sources.
|
||||||
- `tp-propertize`, `tp-apply`, and `tp-watch` as the one-shot string, one-shot buffer-range, and reactive existing-text conveniences over the same direct property/surface core.
|
- `tp-propertize`, `tp-apply`, and `tp-watch` as the one-shot string, one-shot buffer-range, and reactive existing-text conveniences over the same direct property/surface core.
|
||||||
- Retained logical objects with `tp-object-retain` and `tp-object-attach-fragment`, allowing one object to own multiple disjoint physical fragments without placing handles or positions in plans.
|
- Retained logical objects with `tp-object-retain` and `tp-object-attach-fragment`, allowing one object to own multiple disjoint physical fragments without placing handles or positions in plans.
|
||||||
|
|||||||
@ -187,7 +187,7 @@ cycles instead of spinning.
|
|||||||
| Core inspection and debug | `tp-debug-*`, `tp-intervals`, `tp-intervals-map`, `tp-plist`, `tp-text-snapshot`, `tp-empty-p` |
|
| Core inspection and debug | `tp-debug-*`, `tp-intervals`, `tp-intervals-map`, `tp-plist`, `tp-text-snapshot`, `tp-empty-p` |
|
||||||
| Property policy and declarations | `tp-define-property-policy`, `tp-register-text-property`, `tp-text-declarations`, `tp-computed`, `tp-resolve-value`, `tp-merge-declarations`, `tp-define-style`, `tp-style-declarations` |
|
| Property policy and declarations | `tp-define-property-policy`, `tp-register-text-property`, `tp-text-declarations`, `tp-computed`, `tp-resolve-value`, `tp-merge-declarations`, `tp-define-style`, `tp-style-declarations` |
|
||||||
| Static recipes | `define-tp`/`tp-define-layer`, `define-tps`/`define-tp-group`/`tp-define-group`, layer/group queries, undefine/reset/describe |
|
| Static recipes | `define-tp`/`tp-define-layer`, `define-tps`/`define-tp-group`/`tp-define-group`, layer/group queries, undefine/reset/describe |
|
||||||
| Signals and bindings | signal create/read/peek/set/dispose, binding install/read/dispose, `tp-variable-signal`, `tp-with-transaction`, `tp-transaction-participate`, read-only `tp-transaction-active-p`, `tp-runtime-manifest`, counters/reset |
|
| Signals and bindings | signal create/read/peek/set/dispose, binding install/read/dispose, `tp-variable-signal`, `tp-with-transaction`, `tp-transaction-participate`, `tp-transaction-participate-v2`, read-only `tp-transaction-active-p`, `tp-runtime-manifest`, counters/reset |
|
||||||
| Objects and plans | plan/result constructors, `tp-object-ensure`, retain/reuse, fragment/content-range attachment, resolve, mounted/mounts |
|
| Objects and plans | plan/result constructors, `tp-object-ensure`, retain/reuse, fragment/content-range attachment, resolve, mounted/mounts |
|
||||||
| Host ranges | `tp-range-anchor-create`, `tp-range-anchor-live-p`, `tp-object-attach-range`, `tp-range-rebase` |
|
| Host ranges | `tp-range-anchor-create`, `tp-range-anchor-live-p`, `tp-object-attach-range`, `tp-range-rebase` |
|
||||||
| Surfaces | mount/update/scoped update, materialize, live/revision/client-state, at-point, report/report-summary/inspect, unmount |
|
| Surfaces | mount/update/scoped update, materialize, live/revision/client-state, at-point, report/report-summary/inspect, unmount |
|
||||||
|
|||||||
@ -182,7 +182,7 @@ effect 的 input/version tuple,重复或超过图规模上限时停止循环
|
|||||||
| Core inspection 与 debug | `tp-debug-*`、`tp-intervals`、`tp-intervals-map`、`tp-plist`、`tp-text-snapshot`、`tp-empty-p` |
|
| Core inspection 与 debug | `tp-debug-*`、`tp-intervals`、`tp-intervals-map`、`tp-plist`、`tp-text-snapshot`、`tp-empty-p` |
|
||||||
| Property policy 与 declaration | `tp-define-property-policy`、`tp-register-text-property`、`tp-text-declarations`、`tp-computed`、`tp-resolve-value`、`tp-merge-declarations`、`tp-define-style`、`tp-style-declarations` |
|
| Property policy 与 declaration | `tp-define-property-policy`、`tp-register-text-property`、`tp-text-declarations`、`tp-computed`、`tp-resolve-value`、`tp-merge-declarations`、`tp-define-style`、`tp-style-declarations` |
|
||||||
| 静态 recipe | `define-tp`/`tp-define-layer`、`define-tps`/`define-tp-group`/`tp-define-group`、layer/group 查询、undefine/reset/describe |
|
| 静态 recipe | `define-tp`/`tp-define-layer`、`define-tps`/`define-tp-group`/`tp-define-group`、layer/group 查询、undefine/reset/describe |
|
||||||
| Signal 与 binding | signal create/read/peek/set/dispose、binding install/read/dispose、`tp-variable-signal`、`tp-with-transaction`、`tp-transaction-participate`、只读 `tp-transaction-active-p`、`tp-runtime-manifest`、counter/reset |
|
| Signal 与 binding | signal create/read/peek/set/dispose、binding install/read/dispose、`tp-variable-signal`、`tp-with-transaction`、`tp-transaction-participate`、`tp-transaction-participate-v2`、只读 `tp-transaction-active-p`、`tp-runtime-manifest`、counter/reset |
|
||||||
| Object 与 plan | plan/result constructor、`tp-object-ensure`、retain/reuse、fragment/content-range attach、resolve、mounted/mounts |
|
| Object 与 plan | plan/result constructor、`tp-object-ensure`、retain/reuse、fragment/content-range attach、resolve、mounted/mounts |
|
||||||
| Host range | `tp-range-anchor-create`、`tp-range-anchor-live-p`、`tp-object-attach-range`、`tp-range-rebase` |
|
| Host range | `tp-range-anchor-create`、`tp-range-anchor-live-p`、`tp-object-attach-range`、`tp-range-rebase` |
|
||||||
| Surface | mount/update/scoped update、materialize、live/revision/client-state、at-point、report/report-summary/inspect、unmount |
|
| Surface | mount/update/scoped update、materialize、live/revision/client-state、at-point、report/report-summary/inspect、unmount |
|
||||||
|
|||||||
@ -231,6 +231,11 @@ tp-binding-dispose 释放单个 binding。
|
|||||||
(lambda () (my-publish))
|
(lambda () (my-publish))
|
||||||
(lambda () (my-rollback)))
|
(lambda () (my-rollback)))
|
||||||
|
|
||||||
|
(tp-transaction-participate-v2
|
||||||
|
:key 'my-structured-state
|
||||||
|
:stage (lambda () (my-stage))
|
||||||
|
:rollback (lambda () (my-rollback)))
|
||||||
|
|
||||||
(tp-transaction-active-p)
|
(tp-transaction-active-p)
|
||||||
|
|
||||||
(setq tp-transaction-execution-route 'structured) ; structured 或 v1
|
(setq tp-transaction-execution-route 'structured) ; structured 或 v1
|
||||||
@ -247,7 +252,9 @@ tp-binding-dispose 释放单个 binding。
|
|||||||
tp-with-transaction 将 signal、binding、surface 和注册的 transaction
|
tp-with-transaction 将 signal、binding、surface 和注册的 transaction
|
||||||
participant 一起原子处理。participant 必须在 active transaction 内注册;
|
participant 一起原子处理。participant 必须在 active transaction 内注册;
|
||||||
publish 在 surface publication 后、source commit 前运行,失败时按逆序
|
publish 在 surface publication 后、source commit 前运行,失败时按逆序
|
||||||
rollback。tp-variable-signal 用 Emacs variable watcher 适配全局或指定
|
rollback。跨包 structured consumer 使用 `tp-transaction-participate-v2`;它
|
||||||
|
返回 key,不暴露内部 participant 对象。tp-variable-signal 用 Emacs variable
|
||||||
|
watcher 适配全局或指定
|
||||||
Buffer 的变量,不是旧的 $variable API。
|
Buffer 的变量,不是旧的 $variable API。
|
||||||
|
|
||||||
tp-transaction-active-p 是只读边界查询:只在当前 dynamic extent 已进入
|
tp-transaction-active-p 是只读边界查询:只在当前 dynamic extent 已进入
|
||||||
@ -268,7 +275,9 @@ tp-runtime-manifest 返回防御性 capability snapshot;本版本的
|
|||||||
`:execution-routes` 为 `(structured v1)`、`:route-option` 为
|
`:execution-routes` 为 `(structured v1)`、`:route-option` 为
|
||||||
`tp-transaction-execution-route`,兼容字段 `:execution-route` 与
|
`tp-transaction-execution-route`,兼容字段 `:execution-route` 与
|
||||||
`:batch-execution` 也均为 `structured`,`:batch-execute` 为 non-nil。公开
|
`:batch-execution` 也均为 `structured`,`:batch-execute` 为 non-nil。公开
|
||||||
`tp-transaction-participate` 仍是 v1 adapter,manifest 以 `:v1-adapter` 和
|
structured registration 由 `:structured-participant-api` 指向
|
||||||
|
`tp-transaction-participate-v2`;`tp-transaction-participate` 仍是 v1 adapter,
|
||||||
|
manifest 以 `:v1-adapter` 和
|
||||||
`:v1-rollback-route` 明确声明 adapter 与完整旧 route 均保留;
|
`:v1-rollback-route` 明确声明 adapter 与完整旧 route 均保留;
|
||||||
`:single-live-writer` 明确声明 route 不会双写;
|
`:single-live-writer` 明确声明 route 不会双写;
|
||||||
`:batch-artifacts` 与 `:shadow-proof` 也保持 non-nil。
|
`:batch-artifacts` 与 `:shadow-proof` 也保持 non-nil。
|
||||||
|
|||||||
@ -211,6 +211,11 @@ TP 为每个 interval 保存:
|
|||||||
|
|
||||||
`tp-transaction-participate` 允许 client side state 在 surfaces 发布后、source commit 前加入同一 rollback boundary。它保留公共 v1 调用形状,但在默认 structured route 中适配成同一个 participant record 的 `stage` capability,只执行一次。participant key 在一个 outer transaction 中必须唯一。它不是 observer;失败会回滚 transaction。Observer failure 只记录,不回滚已提交结果。
|
`tp-transaction-participate` 允许 client side state 在 surfaces 发布后、source commit 前加入同一 rollback boundary。它保留公共 v1 调用形状,但在默认 structured route 中适配成同一个 participant record 的 `stage` capability,只执行一次。participant key 在一个 outer transaction 中必须唯一。它不是 observer;失败会回滚 transaction。Observer failure 只记录,不回滚已提交结果。
|
||||||
|
|
||||||
|
跨包 consumer 使用公开 `tp-transaction-participate-v2` 直接注册 structured
|
||||||
|
`stage`/`rollback` pair;返回值仍是 key,内部 participant identity、state 与
|
||||||
|
journal 不暴露。完整 v1 execution route 也能执行该同一 v2 participant object,
|
||||||
|
因此 Ebox 可以独立 cutover,而不要求同步改变 TP live route。
|
||||||
|
|
||||||
publication batch、structured participant、final marker 与 tagged outcome 共享
|
publication batch、structured participant、final marker 与 tagged outcome 共享
|
||||||
现有 journal/change-group,不复制第二份 live state。默认 `structured` route 是
|
现有 journal/change-group,不复制第二份 live state。默认 `structured` route 是
|
||||||
唯一 live writer:surface 从 candidate entries 执行,participant 从 candidate
|
唯一 live writer:surface 从 candidate entries 执行,participant 从 candidate
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
(require 'tp-surface)
|
(require 'tp-surface)
|
||||||
|
|
||||||
(declare-function tp--transaction-participate-v2 "tp-reactive" (&rest args))
|
(declare-function tp--transaction-participate-v2 "tp-reactive" (&rest args))
|
||||||
|
(declare-function tp-transaction-participate-v2 "tp-reactive" (&rest args))
|
||||||
(declare-function tp--transaction-participant-protocol "tp-reactive" (value))
|
(declare-function tp--transaction-participant-protocol "tp-reactive" (value))
|
||||||
(declare-function tp--transaction-participant-state "tp-reactive" (value))
|
(declare-function tp--transaction-participant-state "tp-reactive" (value))
|
||||||
(declare-function tp--transaction-participant-journal "tp-reactive" (value))
|
(declare-function tp--transaction-participant-journal "tp-reactive" (value))
|
||||||
@ -388,6 +389,32 @@
|
|||||||
'(:owner old-state)))
|
'(:owner old-state)))
|
||||||
(should (eq (tp--transaction-participant-state participant) 'committed))))
|
(should (eq (tp--transaction-participant-state participant) 'committed))))
|
||||||
|
|
||||||
|
(ert-deftest tp-transaction-test-public-v2-participant-api-spans-both-routes ()
|
||||||
|
"The public v2 API registers one v2 object under structured and v1 writers."
|
||||||
|
(dolist (route '(structured v1))
|
||||||
|
(let ((tp-transaction-execution-route route)
|
||||||
|
(tp-transaction-test--trace nil)
|
||||||
|
participant)
|
||||||
|
(should
|
||||||
|
(eq
|
||||||
|
(tp-with-transaction
|
||||||
|
(should
|
||||||
|
(eq
|
||||||
|
(tp-transaction-participate-v2
|
||||||
|
:key 'public-v2
|
||||||
|
:stage (lambda () (push 'stage tp-transaction-test--trace))
|
||||||
|
:rollback (lambda () (push 'rollback tp-transaction-test--trace))
|
||||||
|
:journal '(:owner public))
|
||||||
|
'public-v2))
|
||||||
|
(setq participant (car tp--transaction-participants))
|
||||||
|
'body-result)
|
||||||
|
'body-result))
|
||||||
|
(should (equal tp-transaction-test--trace '(stage)))
|
||||||
|
(should (eq (tp--transaction-participant-protocol participant) 'v2))
|
||||||
|
(should (equal (tp--transaction-participant-journal participant)
|
||||||
|
'(:owner public)))
|
||||||
|
(should (eq (tp--transaction-participant-state participant) 'committed)))))
|
||||||
|
|
||||||
(ert-deftest tp-transaction-test-v2-participant-stage-fault-rolls-back-prior-only ()
|
(ert-deftest tp-transaction-test-v2-participant-stage-fault-rolls-back-prior-only ()
|
||||||
"A structured stage fault reverses only participants that entered staged."
|
"A structured stage fault reverses only participants that entered staged."
|
||||||
(let ((tp-transaction-test--trace nil)
|
(let ((tp-transaction-test--trace nil)
|
||||||
@ -1604,6 +1631,8 @@
|
|||||||
'tp-transaction-execution-route))
|
'tp-transaction-execution-route))
|
||||||
(should (eq (plist-get manifest :batch-execution) 'structured))
|
(should (eq (plist-get manifest :batch-execution) 'structured))
|
||||||
(should (plist-get manifest :batch-execute))
|
(should (plist-get manifest :batch-execute))
|
||||||
|
(should (eq (plist-get manifest :structured-participant-api)
|
||||||
|
'tp-transaction-participate-v2))
|
||||||
(should (plist-get manifest :v1-adapter))
|
(should (plist-get manifest :v1-adapter))
|
||||||
(should (plist-get manifest :v1-rollback-route))
|
(should (plist-get manifest :v1-rollback-route))
|
||||||
(should (plist-get manifest :single-live-writer))
|
(should (plist-get manifest :single-live-writer))
|
||||||
|
|||||||
@ -744,6 +744,19 @@ participant's opaque owner-local state."
|
|||||||
(tp--transaction-make-participant
|
(tp--transaction-make-participant
|
||||||
key stage rollback 'v2 precommit after-commit journal)))
|
key stage rollback 'v2 precommit after-commit journal)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(cl-defun tp-transaction-participate-v2
|
||||||
|
(&key key stage rollback precommit after-commit journal)
|
||||||
|
"Register a structured rollback-capable participant under KEY.
|
||||||
|
STAGE and ROLLBACK are required no-argument functions. PRECOMMIT may be one
|
||||||
|
declared package-owned validator; AFTER-COMMIT is contained work queued only
|
||||||
|
after final accept. JOURNAL is opaque owner-local rollback state. Return KEY
|
||||||
|
without exposing TP's internal participant object."
|
||||||
|
(tp--transaction-participate-v2
|
||||||
|
:key key :stage stage :rollback rollback :precommit precommit
|
||||||
|
:after-commit after-commit :journal journal)
|
||||||
|
key)
|
||||||
|
|
||||||
(defun tp--transaction-participants-in-registration-order ()
|
(defun tp--transaction-participants-in-registration-order ()
|
||||||
"Return the authoritative participants in deterministic declaration order."
|
"Return the authoritative participants in deterministic declaration order."
|
||||||
(reverse tp--transaction-participants))
|
(reverse tp--transaction-participants))
|
||||||
|
|||||||
1
tp.el
1
tp.el
@ -75,6 +75,7 @@
|
|||||||
:route-option tp-transaction-execution-route
|
:route-option tp-transaction-execution-route
|
||||||
:batch-execution structured
|
:batch-execution structured
|
||||||
:batch-execute t
|
:batch-execute t
|
||||||
|
:structured-participant-api tp-transaction-participate-v2
|
||||||
:v1-adapter t
|
:v1-adapter t
|
||||||
:v1-rollback-route t
|
:v1-rollback-route t
|
||||||
:single-live-writer t
|
:single-live-writer t
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user