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:
+11
-9
@@ -115,7 +115,7 @@ yaml_path = os.environ['YAML_PATH']
|
|||||||
db_path = os.path.splitext(yaml_path)[0] + '.db'
|
db_path = os.path.splitext(yaml_path)[0] + '.db'
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
if os.path.exists(db_path):
|
||||||
conn = sqlite3.connect(db_path, timeout=10.0)
|
conn = sqlite3.connect(db_path, timeout=60.0)
|
||||||
try:
|
try:
|
||||||
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
||||||
if row:
|
if row:
|
||||||
@@ -315,6 +315,9 @@ def _validate(d):
|
|||||||
def get_terminal_set(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')}
|
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)
|
os.makedirs(os.path.dirname(db_path) or '.', exist_ok=True)
|
||||||
conn = sqlite3.connect(db_path, timeout=60.0)
|
conn = sqlite3.connect(db_path, timeout=60.0)
|
||||||
|
|
||||||
@@ -367,7 +370,7 @@ try:
|
|||||||
elif 'tmux_sessions' not in d:
|
elif 'tmux_sessions' not in d:
|
||||||
d['tmux_sessions'] = []
|
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')}
|
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) ---
|
# --- caller mutation (module scope: sees d, yaml, os, glob, subprocess) ---
|
||||||
@@ -400,13 +403,12 @@ try:
|
|||||||
else:
|
else:
|
||||||
conn.execute('DELETE FROM sessions')
|
conn.execute('DELETE FROM sessions')
|
||||||
|
|
||||||
new_terminals = get_terminal_set(d)
|
new_sessions = get_all_sessions_status(d)
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
# Write to YAML ONLY when a session transitions to a finished state
|
# Write to YAML when sessions status or session list changes (e.g. create/stop/resume)
|
||||||
# (Moved after conn.commit() per Claude's feedback)
|
if new_sessions != old_sessions:
|
||||||
if new_terminals != old_terminals:
|
|
||||||
if os.path.exists(yaml_path):
|
if os.path.exists(yaml_path):
|
||||||
try:
|
try:
|
||||||
shutil.copy2(yaml_path, yaml_path + '.bak')
|
shutil.copy2(yaml_path, yaml_path + '.bak')
|
||||||
@@ -509,7 +511,7 @@ def emit(u):
|
|||||||
sessions = []
|
sessions = []
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
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
|
has_sessions_table = False
|
||||||
try:
|
try:
|
||||||
cursor = conn.execute('SELECT data FROM sessions WHERE pane_cwd=?', (ws,))
|
cursor = conn.execute('SELECT data FROM sessions WHERE pane_cwd=?', (ws,))
|
||||||
@@ -621,7 +623,7 @@ elif agent == 'cline':
|
|||||||
ai = {}
|
ai = {}
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
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()
|
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
|
||||||
if row:
|
if row:
|
||||||
ai = json.loads(row[0]).get('agent_identities', {})
|
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'
|
db_path = os.path.splitext(yaml_path)[0] + '.db'
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
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
|
has_sessions_table = False
|
||||||
try:
|
try:
|
||||||
row = conn.execute('SELECT status, data FROM sessions WHERE name=?', (name,)).fetchone()
|
row = conn.execute('SELECT status, data FROM sessions WHERE name=?', (name,)).fetchone()
|
||||||
|
|||||||
@@ -145,6 +145,16 @@ fi
|
|||||||
|
|
||||||
spawn
|
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 준비 대기
|
# TUI 준비 대기
|
||||||
wait_for_tui_ready "$SESSION_NAME" "$AGENT"
|
wait_for_tui_ready "$SESSION_NAME" "$AGENT"
|
||||||
|
|
||||||
@@ -333,6 +343,8 @@ Task: $SUBMIT_JOB_PROMPT"
|
|||||||
WD_PID=$(start_watchdog "$DELEGATE_JOB_ID" "$WORKSPACE")
|
WD_PID=$(start_watchdog "$DELEGATE_JOB_ID" "$WORKSPACE")
|
||||||
echo "watchdog PID: $WD_PID"
|
echo "watchdog PID: $WD_PID"
|
||||||
fi
|
fi
|
||||||
|
# Clear cleanup trap as registration was fully successful
|
||||||
|
trap - EXIT
|
||||||
echo "agent-sessions.yaml updated"
|
echo "agent-sessions.yaml updated"
|
||||||
echo
|
echo
|
||||||
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
|
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ except NameError:
|
|||||||
d = {}
|
d = {}
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
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()
|
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
|
||||||
if row: d = json.loads(row[0])
|
if row: d = json.loads(row[0])
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ db_path = os.path.splitext(yaml_path)[0] + '.db'
|
|||||||
d = {}
|
d = {}
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
if os.path.exists(db_path):
|
||||||
conn = sqlite3.connect(db_path, timeout=10.0)
|
conn = sqlite3.connect(db_path, timeout=60.0)
|
||||||
try:
|
try:
|
||||||
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
||||||
if row:
|
if row:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ d = {}
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
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()
|
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
|
||||||
if row: d = json.loads(row[0])
|
if row: d = json.loads(row[0])
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ db_path = os.path.splitext(yaml_path)[0] + '.db'
|
|||||||
d = {}
|
d = {}
|
||||||
try:
|
try:
|
||||||
if os.path.exists(db_path):
|
if os.path.exists(db_path):
|
||||||
conn = sqlite3.connect(db_path, timeout=10.0)
|
conn = sqlite3.connect(db_path, timeout=60.0)
|
||||||
try:
|
try:
|
||||||
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
row = conn.execute('SELECT data FROM sessions WHERE name=?', (name,)).fetchone()
|
||||||
if row:
|
if row:
|
||||||
|
|||||||
Reference in New Issue
Block a user