diff --git a/CHANGELOG.md b/CHANGELOG.md index b329316..ebe2874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. - Supported `tp-transaction-execution-route` kill switch with `structured` as 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. - `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. diff --git a/README.md b/README.md index fefcd13..fb99678 100644 --- a/README.md +++ b/README.md @@ -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` | | 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 | -| 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 | | 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 | diff --git a/README_CN.md b/README_CN.md index a5d8261..8415628 100644 --- a/README_CN.md +++ b/README_CN.md @@ -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` | | 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 | -| 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 | | 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 | diff --git a/docs/API-REFERENCE.md b/docs/API-REFERENCE.md index 51b355b..83b6355 100644 --- a/docs/API-REFERENCE.md +++ b/docs/API-REFERENCE.md @@ -231,6 +231,11 @@ tp-binding-dispose 释放单个 binding。 (lambda () (my-publish)) (lambda () (my-rollback))) +(tp-transaction-participate-v2 + :key 'my-structured-state + :stage (lambda () (my-stage)) + :rollback (lambda () (my-rollback))) + (tp-transaction-active-p) (setq tp-transaction-execution-route 'structured) ; structured 或 v1 @@ -247,7 +252,9 @@ tp-binding-dispose 释放单个 binding。 tp-with-transaction 将 signal、binding、surface 和注册的 transaction participant 一起原子处理。participant 必须在 active transaction 内注册; 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。 tp-transaction-active-p 是只读边界查询:只在当前 dynamic extent 已进入 @@ -268,7 +275,9 @@ tp-runtime-manifest 返回防御性 capability snapshot;本版本的 `:execution-routes` 为 `(structured v1)`、`:route-option` 为 `tp-transaction-execution-route`,兼容字段 `:execution-route` 与 `: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 均保留; `:single-live-writer` 明确声明 route 不会双写; `:batch-artifacts` 与 `:shadow-proof` 也保持 non-nil。 diff --git a/docs/API-SEMANTICS.md b/docs/API-SEMANTICS.md index 5db443d..dea442e 100644 --- a/docs/API-SEMANTICS.md +++ b/docs/API-SEMANTICS.md @@ -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 只记录,不回滚已提交结果。 +跨包 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 共享 现有 journal/change-group,不复制第二份 live state。默认 `structured` route 是 唯一 live writer:surface 从 candidate entries 执行,participant 从 candidate diff --git a/tests/tp-transaction-tests.el b/tests/tp-transaction-tests.el index fc7519c..d02ee7e 100644 --- a/tests/tp-transaction-tests.el +++ b/tests/tp-transaction-tests.el @@ -17,6 +17,7 @@ (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-participant-protocol "tp-reactive" (value)) (declare-function tp--transaction-participant-state "tp-reactive" (value)) (declare-function tp--transaction-participant-journal "tp-reactive" (value)) @@ -388,6 +389,32 @@ '(:owner old-state))) (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 () "A structured stage fault reverses only participants that entered staged." (let ((tp-transaction-test--trace nil) @@ -1604,6 +1631,8 @@ 'tp-transaction-execution-route)) (should (eq (plist-get manifest :batch-execution) 'structured)) (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-rollback-route)) (should (plist-get manifest :single-live-writer)) diff --git a/tp-reactive.el b/tp-reactive.el index 6127ee5..4b56c99 100644 --- a/tp-reactive.el +++ b/tp-reactive.el @@ -744,6 +744,19 @@ participant's opaque owner-local state." (tp--transaction-make-participant 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 () "Return the authoritative participants in deterministic declaration order." (reverse tp--transaction-participants)) diff --git a/tp.el b/tp.el index 3885f15..1d0a9aa 100644 --- a/tp.el +++ b/tp.el @@ -75,6 +75,7 @@ :route-option tp-transaction-execution-route :batch-execution structured :batch-execute t + :structured-participant-api tp-transaction-participate-v2 :v1-adapter t :v1-rollback-route t :single-live-writer t