Summary
Implement gaia deals watch as a proper background daemon that persists across terminal sessions, with PID management, log rotation, and graceful shutdown — following the existing gaia api start --background pattern.
Motivation
The scheduled price checker needs to run continuously even after the user closes their terminal. The API server already has this pattern (gaia api start --background with PID file + log file). The DealAgent daemon reuses this pattern.
Design
Daemon Lifecycle
gaia deals watch # Start daemon (default 6h interval)
gaia deals watch --interval 2h # Start with custom interval
gaia deals watch --status # Show daemon status + next check time
gaia deals watch --stop # Graceful shutdown
gaia deals watch --logs # Tail the daemon log
gaia deals watch --logs -n 50 # Show last 50 log lines
Implementation (follows API server pattern)
# src/gaia/agents/deals/daemon.py
import subprocess
import os
import signal
PIDFILE = os.path.expanduser("~/.gaia/deals/deals_watch.pid")
LOGFILE = os.path.expanduser("~/.gaia/deals/deals_watch.log")
def start_daemon(interval_hours: float = 6.0):
"""Start price watcher as background process."""
if is_running():
print(f"Deal watcher already running (PID {get_pid()})")
return
cmd = [sys.executable, "-m", "gaia.agents.deals.watcher",
"--interval", str(interval_hours)]
proc = subprocess.Popen(
cmd, stdout=open(LOGFILE, "a"), stderr=subprocess.STDOUT,
start_new_session=True
)
with open(PIDFILE, "w") as f:
f.write(str(proc.pid))
print(f"Deal watcher started (PID {proc.pid}, interval {interval_hours}h)")
print(f"Logs: {LOGFILE}")
def stop_daemon():
"""Gracefully stop the daemon."""
pid = get_pid()
if pid and is_running():
os.kill(pid, signal.SIGTERM)
os.remove(PIDFILE)
print(f"Deal watcher stopped (PID {pid})")
def get_status() -> Dict:
"""Return daemon status: running, PID, next check, items tracked."""
Log Rotation
- Max log size: 10MB
- Keep 3 rotated files
- Uses
logging.handlers.RotatingFileHandler
Startup Integration
Optionally auto-start on gaia deals if watchlist is non-empty:
You have 5 products on your watchlist. Start background monitoring? [Y/n]
Acceptance Criteria
Phase
Phase 2 — Tracking & Alerts
Dependencies
- Scheduled price checking (Phase 2)
- Follows
gaia api start --background pattern from src/gaia/api/app.py
Summary
Implement
gaia deals watchas a proper background daemon that persists across terminal sessions, with PID management, log rotation, and graceful shutdown — following the existinggaia api start --backgroundpattern.Motivation
The scheduled price checker needs to run continuously even after the user closes their terminal. The API server already has this pattern (
gaia api start --backgroundwith PID file + log file). The DealAgent daemon reuses this pattern.Design
Daemon Lifecycle
Implementation (follows API server pattern)
Log Rotation
logging.handlers.RotatingFileHandlerStartup Integration
Optionally auto-start on
gaia dealsif watchlist is non-empty:Acceptance Criteria
gaia deals watchstarts background process with PID filegaia deals watch --stopgracefully terminates daemongaia deals watch --statusshows running state, PID, next check, item countgaia deals watch --logstails the log filePhase
Phase 2 — Tracking & Alerts
Dependencies
gaia api start --backgroundpattern fromsrc/gaia/api/app.py