mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-05 07:41:39 +00:00
fix(kanban): clear _INITIALIZED_PATHS in remove_board so recycled DBs re-init schema
Archiving or deleting a board via remove_board() leaves the path's
"schema already initialized" entry in the module-level cache. A
concurrent connect(board=<slug>) call (e.g. the dashboard event-stream
poll loop) then:
1. resolves the same kanban.db path,
2. recreates the directory + an empty sqlite file because
connect() does mkdir(parents=True, exist_ok=True),
3. skips the CREATE TABLE pass because the cache entry says the
schema is already in place,
4. errors on the next read with `no such table: task_events`.
Drop the cache entry before mutating the filesystem so the fresh file
gets a proper schema init on next connect(). Applies to both
archive=True (rename) and archive=False (rmtree) branches.
Fixes #23833.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
028bbc5425
commit
d62964cdfa
2 changed files with 36 additions and 0 deletions
|
|
@ -258,6 +258,37 @@ class TestBoardCRUD:
|
|||
kb.remove_board("pinned")
|
||||
assert kb.get_current_board() == "default"
|
||||
|
||||
@pytest.mark.parametrize("archive", [True, False])
|
||||
def test_remove_clears_init_cache_for_recreated_db(self, fresh_home, archive):
|
||||
# Regression for #23833: poll loops that call connect(board=slug) right
|
||||
# after remove_board() recreate an empty kanban.db at the same path
|
||||
# (connect() does mkdir(exist_ok=True)). If _INITIALIZED_PATHS still
|
||||
# contains the resolved path, the CREATE TABLE pass is skipped and
|
||||
# downstream readers hit `no such table: task_events`.
|
||||
kb.create_board("recycle")
|
||||
# First connect populates _INITIALIZED_PATHS for this DB.
|
||||
with kb.connect(board="recycle") as conn:
|
||||
kb.create_task(conn, title="t1", assignee="dev")
|
||||
db_path = kb.board_dir("recycle") / "kanban.db"
|
||||
assert str(db_path.resolve()) in kb._INITIALIZED_PATHS
|
||||
|
||||
kb.remove_board("recycle", archive=archive)
|
||||
# remove_board must drop the cache entry so a re-create through
|
||||
# connect() gets a fresh schema-init pass.
|
||||
assert str(db_path.resolve()) not in kb._INITIALIZED_PATHS
|
||||
|
||||
# Simulate the event-stream poll: re-open the same slug. connect()
|
||||
# recreates the directory + empty .db; the schema must be re-applied.
|
||||
with kb.connect(board="recycle") as conn:
|
||||
tables = {
|
||||
row[0]
|
||||
for row in conn.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table'"
|
||||
)
|
||||
}
|
||||
assert "task_events" in tables
|
||||
assert "tasks" in tables
|
||||
|
||||
def test_rename_updates_metadata(self, fresh_home):
|
||||
kb.create_board("slug-immutable")
|
||||
kb.write_board_metadata("slug-immutable", name="New Display Name")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue