fix(deploy): resolve SQL timeouts, YAML drift, and orphaned tmux sessions

- lib.sh: update atomic_dump_yaml to sync with YAML on any active session status change; set reader timeouts to 60.0s
- create_session.sh: add exit trap cleanup_tmux_on_error to rollback spawned tmux sessions on initialization failures
- reconcile.sh, update_yaml_resumed.sh, status.sh, stop_session.sh: align SQLite connection timeout values to 60.0s
This commit is contained in:
2026-07-10 09:21:07 +09:00
parent 6408f4a5ec
commit 3a9964c0e2
6 changed files with 27 additions and 13 deletions
+11 -9
View File
@@ -115,7 +115,7 @@ yaml_path = os.environ['YAML_PATH']
db_path = os.path.splitext(yaml_path)[0] + '.db'
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
try:
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
if row:
@@ -315,6 +315,9 @@ def _validate(d):
def get_terminal_set(d):
return {s.get('name'): s.get('status') for s in d.get('tmux_sessions', []) if s.get('status') in ('stopped', 'terminated', 'archived')}
def get_all_sessions_status(d):
return {s.get('name'): s.get('status') for s in d.get('tmux_sessions', [])}
os.makedirs(os.path.dirname(db_path) or '.', exist_ok=True)
conn = sqlite3.connect(db_path, timeout=60.0)
@@ -367,7 +370,7 @@ try:
elif 'tmux_sessions' not in d:
d['tmux_sessions'] = []
old_terminals = get_terminal_set(d)
old_sessions = get_all_sessions_status(d)
old_roles = {s.get('name'): s.get('role') for s in db_sessions if s.get('role')}
# --- caller mutation (module scope: sees d, yaml, os, glob, subprocess) ---
@@ -400,13 +403,12 @@ try:
else:
conn.execute('DELETE FROM sessions')
new_terminals = get_terminal_set(d)
new_sessions = get_all_sessions_status(d)
conn.commit()
# Write to YAML ONLY when a session transitions to a finished state
# (Moved after conn.commit() per Claude's feedback)
if new_terminals != old_terminals:
# Write to YAML when sessions status or session list changes (e.g. create/stop/resume)
if new_sessions != old_sessions:
if os.path.exists(yaml_path):
try:
shutil.copy2(yaml_path, yaml_path + '.bak')
@@ -509,7 +511,7 @@ def emit(u):
sessions = []
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
has_sessions_table = False
try:
cursor = conn.execute('SELECT data FROM sessions WHERE pane_cwd=?', (ws,))
@@ -621,7 +623,7 @@ elif agent == 'cline':
ai = {}
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
if row:
ai = json.loads(row[0]).get('agent_identities', {})
@@ -687,7 +689,7 @@ yaml_path = os.environ['YAML_PATH']
db_path = os.path.splitext(yaml_path)[0] + '.db'
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
has_sessions_table = False
try:
row = conn.execute('SELECT status, data FROM sessions WHERE name=?', (name,)).fetchone()
@@ -145,6 +145,16 @@ fi
spawn
# Trap for rolling back/cleaning up tmux session if script exits due to error
cleanup_tmux_on_error() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "⚠️ Error occurred during initialization. Rolling back and killing tmux session '$SESSION_NAME'..." >&2
_tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
fi
}
trap cleanup_tmux_on_error EXIT
# TUI 준비 대기
wait_for_tui_ready "$SESSION_NAME" "$AGENT"
@@ -333,6 +343,8 @@ Task: $SUBMIT_JOB_PROMPT"
WD_PID=$(start_watchdog "$DELEGATE_JOB_ID" "$WORKSPACE")
echo "watchdog PID: $WD_PID"
fi
# Clear cleanup trap as registration was fully successful
trap - EXIT
echo "agent-sessions.yaml updated"
echo
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
@@ -301,7 +301,7 @@ except NameError:
d = {}
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
if row: d = json.loads(row[0])
@@ -65,7 +65,7 @@ db_path = os.path.splitext(yaml_path)[0] + '.db'
d = {}
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
try:
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
if row:
@@ -42,7 +42,7 @@ d = {}
import sqlite3
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
if row: d = json.loads(row[0])
@@ -91,7 +91,7 @@ db_path = os.path.splitext(yaml_path)[0] + '.db'
d = {}
try:
if os.path.exists(db_path):
conn = sqlite3.connect(db_path, timeout=10.0)
conn = sqlite3.connect(db_path, timeout=60.0)
try:
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
if row: