Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
"""Cross-process ordering for asynchronous session Git metadata probes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
import threading
|
||||
|
||||
from hermes_state import SCHEMA_VERSION, SessionDB
|
||||
|
||||
|
||||
def _open_pair(tmp_path):
|
||||
path = tmp_path / "state.db"
|
||||
first = SessionDB(db_path=path)
|
||||
second = SessionDB(db_path=path)
|
||||
first.create_session("session", "desktop", cwd="/repo/A")
|
||||
return first, second
|
||||
|
||||
|
||||
def _require_generation(value: int | None) -> int:
|
||||
assert isinstance(value, int) and not isinstance(value, bool)
|
||||
return value
|
||||
|
||||
|
||||
def test_delayed_probe_cannot_overwrite_newer_a_b_a_claim(tmp_path):
|
||||
first, second = _open_pair(tmp_path)
|
||||
release_old = threading.Event()
|
||||
old_finished = threading.Event()
|
||||
old_result = []
|
||||
try:
|
||||
old_generation = _require_generation(
|
||||
first.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
|
||||
def publish_old_probe():
|
||||
assert release_old.wait(5)
|
||||
old_result.append(
|
||||
first.publish_session_git_metadata(
|
||||
"session",
|
||||
"/repo/A",
|
||||
old_generation,
|
||||
"stale-branch",
|
||||
"/repo/stale-root",
|
||||
)
|
||||
)
|
||||
old_finished.set()
|
||||
|
||||
worker = threading.Thread(target=publish_old_probe)
|
||||
worker.start()
|
||||
|
||||
second.update_session_cwd("session", "/repo/B")
|
||||
new_generation = _require_generation(
|
||||
second.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
assert new_generation > old_generation
|
||||
assert second.publish_session_git_metadata(
|
||||
"session",
|
||||
"/repo/A",
|
||||
new_generation,
|
||||
"new-branch",
|
||||
"/repo/new-root",
|
||||
)
|
||||
|
||||
release_old.set()
|
||||
assert old_finished.wait(5)
|
||||
worker.join(timeout=5)
|
||||
assert not worker.is_alive()
|
||||
assert old_result == [False]
|
||||
|
||||
row = second.get_session("session")
|
||||
assert row is not None
|
||||
assert row["cwd"] == "/repo/A"
|
||||
assert row["git_branch"] == "new-branch"
|
||||
assert row["git_repo_root"] == "/repo/new-root"
|
||||
finally:
|
||||
release_old.set()
|
||||
first.close()
|
||||
second.close()
|
||||
|
||||
|
||||
def test_repeated_same_cwd_claim_invalidates_older_probe(tmp_path):
|
||||
first, second = _open_pair(tmp_path)
|
||||
try:
|
||||
old_generation = _require_generation(
|
||||
first.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
new_generation = _require_generation(
|
||||
second.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
|
||||
assert new_generation > old_generation
|
||||
assert second.publish_session_git_metadata(
|
||||
"session", "/repo/A", new_generation, "new", "/repo/A"
|
||||
)
|
||||
assert not first.publish_session_git_metadata(
|
||||
"session", "/repo/A", old_generation, "old", "/repo/old"
|
||||
)
|
||||
row = second.get_session("session")
|
||||
assert row is not None
|
||||
assert row["git_branch"] == "new"
|
||||
finally:
|
||||
first.close()
|
||||
second.close()
|
||||
|
||||
|
||||
def test_cwd_move_clears_metadata_in_same_claim(tmp_path):
|
||||
db = SessionDB(db_path=tmp_path / "state.db")
|
||||
try:
|
||||
db.create_session("session", "desktop", cwd="/repo/A")
|
||||
generation = _require_generation(
|
||||
db.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
assert db.publish_session_git_metadata(
|
||||
"session", "/repo/A", generation, "main", "/repo/A"
|
||||
)
|
||||
|
||||
moved_generation = _require_generation(
|
||||
db.update_session_cwd("session", "/repo/B")
|
||||
)
|
||||
row = db.get_session("session")
|
||||
assert row is not None
|
||||
assert moved_generation > generation
|
||||
assert row["cwd"] == "/repo/B"
|
||||
assert row["git_branch"] is None
|
||||
assert row["git_repo_root"] is None
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_explicit_move_replaces_metadata_and_claims_generation(tmp_path):
|
||||
db = SessionDB(db_path=tmp_path / "state.db")
|
||||
try:
|
||||
db.create_session("session", "desktop", cwd="/repo/A")
|
||||
initial_generation = _require_generation(
|
||||
db.update_session_cwd(
|
||||
"session",
|
||||
"/repo/A",
|
||||
git_branch="main",
|
||||
git_repo_root="/repo/A",
|
||||
)
|
||||
)
|
||||
|
||||
moved_generation = _require_generation(
|
||||
db.update_session_cwd(
|
||||
"session",
|
||||
"/outside-git",
|
||||
replace_git_meta=True,
|
||||
)
|
||||
)
|
||||
|
||||
row = db.get_session("session")
|
||||
assert row is not None
|
||||
assert moved_generation > initial_generation
|
||||
assert row["cwd"] == "/outside-git"
|
||||
assert row["git_branch"] is None
|
||||
assert row["git_repo_root"] is None
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_failed_new_probe_still_invalidates_older_worker(tmp_path):
|
||||
first, second = _open_pair(tmp_path)
|
||||
try:
|
||||
baseline = _require_generation(
|
||||
first.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
assert first.publish_session_git_metadata(
|
||||
"session", "/repo/A", baseline, "baseline", "/repo/A"
|
||||
)
|
||||
old_generation = _require_generation(
|
||||
first.update_session_cwd("session", "/repo/A")
|
||||
)
|
||||
second.update_session_cwd("session", "/repo/A")
|
||||
|
||||
assert not first.publish_session_git_metadata(
|
||||
"session", "/repo/A", old_generation, "stale", "/repo/stale"
|
||||
)
|
||||
row = second.get_session("session")
|
||||
assert row is not None
|
||||
assert row["git_branch"] == "baseline"
|
||||
assert row["git_repo_root"] == "/repo/A"
|
||||
finally:
|
||||
first.close()
|
||||
second.close()
|
||||
|
||||
|
||||
def test_generation_authority_is_scoped_to_each_profile_database(tmp_path):
|
||||
first = SessionDB(db_path=tmp_path / "profile-a.db")
|
||||
second = SessionDB(db_path=tmp_path / "profile-b.db")
|
||||
try:
|
||||
first.create_session("same-id", "desktop", cwd="/a")
|
||||
second.create_session("same-id", "desktop", cwd="/b")
|
||||
first_generation = _require_generation(
|
||||
first.update_session_cwd("same-id", "/a")
|
||||
)
|
||||
second_generation = _require_generation(
|
||||
second.update_session_cwd("same-id", "/b")
|
||||
)
|
||||
|
||||
assert first.publish_session_git_metadata(
|
||||
"same-id", "/a", first_generation, "a", "/a"
|
||||
)
|
||||
assert second.publish_session_git_metadata(
|
||||
"same-id", "/b", second_generation, "b", "/b"
|
||||
)
|
||||
first_row = first.get_session("same-id")
|
||||
second_row = second.get_session("same-id")
|
||||
assert first_row is not None
|
||||
assert second_row is not None
|
||||
assert first_row["git_branch"] == "a"
|
||||
assert second_row["git_branch"] == "b"
|
||||
finally:
|
||||
first.close()
|
||||
second.close()
|
||||
|
||||
|
||||
def test_legacy_sessions_table_reconciles_generation_column(tmp_path):
|
||||
path = tmp_path / "state.db"
|
||||
SessionDB(db_path=path).close()
|
||||
conn = sqlite3.connect(path)
|
||||
try:
|
||||
conn.execute("ALTER TABLE sessions DROP COLUMN git_metadata_generation")
|
||||
conn.execute("UPDATE schema_version SET version = 25")
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
reopened = SessionDB(db_path=path)
|
||||
try:
|
||||
verify = sqlite3.connect(path)
|
||||
try:
|
||||
columns = {
|
||||
row[1]
|
||||
for row in verify.execute("PRAGMA table_info('sessions')")
|
||||
}
|
||||
finally:
|
||||
verify.close()
|
||||
assert "git_metadata_generation" in columns
|
||||
assert reopened._conn.execute(
|
||||
"SELECT version FROM schema_version"
|
||||
).fetchone()[0] == SCHEMA_VERSION
|
||||
reopened.create_session("session", "desktop", cwd="/repo")
|
||||
assert reopened.update_session_cwd("session", "/repo") == 1
|
||||
finally:
|
||||
reopened.close()
|
||||
|
||||
|
||||
def test_compact_session_rows_do_not_expose_internal_generation(tmp_path):
|
||||
db = SessionDB(db_path=tmp_path / "state.db")
|
||||
try:
|
||||
db.create_session("session", "desktop", cwd="/repo")
|
||||
db.update_session_cwd("session", "/repo")
|
||||
|
||||
rows = db.list_sessions_rich(compact_rows=True)
|
||||
assert len(rows) == 1
|
||||
assert "git_metadata_generation" not in rows[0]
|
||||
finally:
|
||||
db.close()
|
||||
Reference in New Issue
Block a user