diff --git a/plugins/memory/holographic/store.py b/plugins/memory/holographic/store.py index a521b865d6b..bf58d7a22db 100644 --- a/plugins/memory/holographic/store.py +++ b/plugins/memory/holographic/store.py @@ -129,7 +129,13 @@ class MemoryStore: self._hrr_available = hrr._HAS_NUMPY # Acquire (or open) the process-wide shared connection for this DB. - self._key = str(self.db_path) + # resolve() (not just expanduser) so symlinked/relative paths to the + # same file share ONE connection instead of silently reintroducing + # the multi-writer contention this registry exists to prevent. + try: + self._key = str(self.db_path.resolve()) + except OSError: + self._key = str(self.db_path) with MemoryStore._shared_guard: entry = MemoryStore._shared.get(self._key) if entry is None: diff --git a/scripts/release.py b/scripts/release.py index cfd36bb9476..6b3f9043baf 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -258,6 +258,7 @@ AUTHOR_MAP = { "sswdarius@gmail.com": "necoweb3", "bassisho@Mac-mini-bassis.local": "hydracoco7", # PR #61382 salvage (id-less cron job freeze) "AlexFucuson9@users.noreply.github.com": "AlexFucuson9", # PR #61209 salvage (hygiene compression data loss) + "email@adambig.gs": "adambiggs", # PR #43819 salvage (holographic shared SQLite connection) "t.chen@aftership.com": "cypctlinux", # PR #52403 salvage (Slack bot/workflow auth before no-user-id guard) "30854794+YLChen-007@users.noreply.github.com": "YLChen-007", # PR #26965 (approval remote command substitution) "1078345+egilewski@users.noreply.github.com": "egilewski", # co-author, PR #40663 diff --git a/tests/plugins/memory/test_holographic_store.py b/tests/plugins/memory/test_holographic_store.py index 59d8ee1cb81..df351864b00 100644 --- a/tests/plugins/memory/test_holographic_store.py +++ b/tests/plugins/memory/test_holographic_store.py @@ -68,6 +68,24 @@ class TestSharedConnection: a.close() b.close() + def test_symlinked_path_shares_connection(self, tmp_path): + """A symlink to the same DB file must hit the same registry entry — + otherwise two connections to one file silently reintroduce the + multi-writer contention the registry exists to prevent.""" + real_dir = tmp_path / "real" + real_dir.mkdir() + link_dir = tmp_path / "link" + link_dir.symlink_to(real_dir) + + a = MemoryStore(real_dir / "memory_store.db") + b = MemoryStore(link_dir / "memory_store.db") + try: + assert a._conn is b._conn + assert len(MemoryStore._shared) == 1 + finally: + a.close() + b.close() + def test_writes_visible_across_instances(self, db_path): a = MemoryStore(db_path) b = MemoryStore(db_path)