feat: expose transaction activity boundary

This commit is contained in:
Kinneyzhang 2026-08-27 22:49:21 +08:00
parent 31304c1906
commit c2525a137b
5 changed files with 23 additions and 2 deletions

View File

@ -174,7 +174,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`, counters/reset |
| 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`, 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 |

View File

@ -171,7 +171,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`、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-active-p`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 |

View File

@ -231,6 +231,8 @@ tp-binding-dispose 释放单个 binding。
(lambda () (my-publish))
(lambda () (my-rollback)))
(tp-transaction-active-p)
(tp-variable-signal 'my-variable)
(tp-variable-signal 'my-buffer-variable some-buffer)
(tp-reactive-counters)
@ -244,6 +246,11 @@ publish 在 surface publication 后、source commit 前运行,失败时按逆
rollback。tp-variable-signal 用 Emacs variable watcher 适配全局或指定
Buffer 的变量,不是旧的 $variable API。
tp-transaction-active-p 是只读边界查询:只在当前 dynamic extent 已进入
或加入 TP transaction 时返回严格的 t否则返回 nil。它不暴露 transaction
对象、participant 或内部状态,调用方只能用它在 mutation 前拒绝不支持的
嵌套事务边界。
ETAF registers one opaque participant for its immutable generation and Ebox
client state. Its publish is paired with rollback across TP final accept; the
ETAF runtime separately records effect input/version tuples and reports a

View File

@ -160,6 +160,15 @@
(should (= calls 2))
(should (= (plist-get (tp-reactive-counters) :recomputed) 1)))))
(ert-deftest tp-binding-test-public-transaction-state-follows-dynamic-extent ()
"The public transaction predicate is true only inside joined transactions."
(should-not (tp-transaction-active-p))
(tp-with-transaction
(should (tp-transaction-active-p))
(tp-with-transaction
(should (tp-transaction-active-p))))
(should-not (tp-transaction-active-p)))
(ert-deftest tp-binding-test-transaction-commits-signals-in-first-touch-order ()
"Touched signals commit once in first-touch order, including net reverts."
(tp-binding-test--isolated

View File

@ -68,6 +68,11 @@
:subscription-added 0 :subscription-removed 0))
(defvar tp--transaction-active nil)
;;;###autoload
(defun tp-transaction-active-p ()
"Return non-nil while the current dynamic extent is in a TP transaction."
(and tp--transaction-active t))
(defvar tp--transaction-signal-values nil)
(defvar tp--transaction-signals nil)
(defvar tp--transaction-dirty-set nil)