From 013c1785b35bab9c2c29d89b04c633f52bc1b485 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Wed, 29 Apr 2026 17:02:35 +0800 Subject: [PATCH 1/2] feat(index.ts): dual-track registration with early claim + rollback support --- index.ts | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/index.ts b/index.ts index f9cfe29b..10a2f9c5 100644 --- a/index.ts +++ b/index.ts @@ -1675,6 +1675,21 @@ const pluginVersion = getPluginVersion(); // hook/tool registration for the new API instance" regression that rwmjhb identified. let _registeredApis = new WeakSet(); +// Dual-track registration: alongside WeakSet (GC-safe), use a Map for explicit +// rollback tracking and test inspection. WeakSet handles GC safety; Map provides +// manual clearability and _getRegisteredApisForTest() export. +// Track: _registeredApisMap (explicit claim/rollback) + _registeredApis (WeakSet guard) +let _registeredApisMap = new Map(); + +/** + * Returns the internal registration Map — for unit test inspection only. + * Do NOT mutate from outside the plugin. + * @public (test API) + */ +export function _getRegisteredApisForTest(): Map { + return _registeredApisMap; +} + // ============================================================================ // Hook Event Deduplication (Phase 1) // ============================================================================ @@ -1930,21 +1945,23 @@ const memoryLanceDBProPlugin = { // - Memory heap growth from repeated resource creation (~9 calls/process) // - Accumulated session Maps being lost on re-registration // - // IMPORTANT: _registeredApis.add(api) is called AFTER successful init. - // This ensures that if _initPluginState throws, the api is NOT in the - // WeakSet, allowing a subsequent register() call with the same api to retry. - // (The old placement — before init — caused permanent breakage on init failure.) + // Dual-track claim: we record registration BEFORE attempting init so that + // if init fails, we can explicitly roll back the Map entry — enabling a + // subsequent register() retry with the same API object. + // - _registeredApis (WeakSet): GC-safe singleton guard (Phase 2 guard) + // - _registeredApisMap (Map): explicit claim/rollback for test inspection // ======================================================================== + _registeredApis.add(api); // claim before init (Phase 2 singleton guard) + _registeredApisMap.set(api, true); // dual-track: explicit claim for rollback let singleton: typeof _singletonState; try { if (!_singletonState) { _singletonState = _initPluginState(api); } singleton = _singletonState; } catch (err) { api.logger.error(`memory-lancedb-pro: _initPluginState failed — ${String(err)}`); + _registeredApisMap.delete(api); // dual-track rollback: init failed, un-claim throw err; } - _registeredApis.add(api); - const { config, resolvedDbPath, @@ -4326,6 +4343,7 @@ export { getDefaultMdMirrorDir }; */ export function resetRegistration() { _registeredApis = new WeakSet(); + _registeredApisMap.clear(); // dual-track: clear Map alongside WeakSet _singletonState = null; _hookEventDedup.clear(); } From 5b26ac6b3aeb284896dcfcc6293deffe2d62f9f1 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Wed, 29 Apr 2026 17:10:53 +0800 Subject: [PATCH 2/2] fix(index.ts): rollback WeakSet claim on init failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex PR #721 review: if _initPluginState throws, only _registeredApisMap was rolled back, but _registeredApis.add(api) happened BEFORE the try block so the WeakSet entry remained. This caused register()'s _registeredApis.has(api) guard to permanently skip retry — plugin could not recover from transient init failures. Fix: delete from both WeakSet and Map in the catch block. --- index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index 10a2f9c5..5871791c 100644 --- a/index.ts +++ b/index.ts @@ -1959,7 +1959,8 @@ const memoryLanceDBProPlugin = { singleton = _singletonState; } catch (err) { api.logger.error(`memory-lancedb-pro: _initPluginState failed — ${String(err)}`); - _registeredApisMap.delete(api); // dual-track rollback: init failed, un-claim + _registeredApis.delete(api); // dual-track rollback: WeakSet un-claim + _registeredApisMap.delete(api); // dual-track rollback: Map un-claim throw err; } const {