add live console status to sync watch

This commit is contained in:
phernandez
2025-02-02 21:53:25 -06:00
parent 72210429c4
commit aa094bfb34
+76 -33
View File
@@ -8,7 +8,10 @@ from datetime import datetime
from pathlib import Path
from typing import List, Optional
from rich import box
from rich.console import Console
from rich.live import Live
from rich.table import Table
from watchfiles import awatch, Change
import os
@@ -16,8 +19,6 @@ from basic_memory.config import ProjectConfig
from basic_memory.sync.sync_service import SyncService
from basic_memory.services.file_service import FileService
console = Console()
class WatchEvent(BaseModel):
timestamp: datetime
@@ -79,6 +80,56 @@ class WatchService:
self.state = WatchServiceState()
self.status_path = config.home / ".basic-memory" / "watch-status.json"
self.status_path.parent.mkdir(parents=True, exist_ok=True)
self.console = Console()
def generate_table(self) -> Table:
"""Generate status display table"""
table = Table(title="Basic Memory Sync Status")
# Add status row
table.add_column("Status", style="cyan")
table.add_column("Last Scan", style="cyan")
table.add_column("Files", style="cyan")
table.add_column("Errors", style="red")
# Add main status row
table.add_row(
"✓ Running" if self.state.running else "✗ Stopped",
self.state.last_scan.strftime("%H:%M:%S") if self.state.last_scan else "-",
str(self.state.synced_files),
f"{self.state.error_count} ({self.state.last_error.strftime('%H:%M:%S') if self.state.last_error else 'none'})",
)
if self.state.recent_events:
# Add recent events
table.add_section()
table.add_row("Recent Events", "", "", "")
for event in self.state.recent_events[:5]: # Show last 5 events
color = {
"new": "green",
"modified": "yellow",
"moved": "blue",
"deleted": "red",
"error": "red",
}.get(event.action, "white")
icon = {
"new": "",
"modified": "",
"moved": "",
"deleted": "",
"error": "!",
}.get(event.action, "*")
table.add_row(
f"[{color}]{icon} {event.action}[/{color}]",
event.timestamp.strftime("%H:%M:%S"),
f"[{color}]{event.path}[/{color}]",
f"[dim]{event.checksum[:8] if event.checksum else ''}[/dim]",
)
return table
async def run(self):
"""Watch for file changes and sync them"""
@@ -86,24 +137,26 @@ class WatchService:
self.state.start_time = datetime.now()
await self.write_status()
console.print("\n[cyan]Watching for changes...[/cyan]")
try:
async for changes in awatch(
self.config.home,
watch_filter=self.filter_changes,
debounce=self.config.sync_delay,
recursive=True,
):
# just sync the whole dir
await self.handle_changes(self.config.home)
with Live(self.generate_table(), refresh_per_second=4, console=self.console) as live:
try:
async for changes in awatch(
self.config.home,
watch_filter=self.filter_changes,
debounce=self.config.sync_delay,
recursive=True,
):
# Process changes
await self.handle_changes(self.config.home)
# Update display
live.update(self.generate_table())
except Exception as e:
self.state.record_error(str(e))
await self.write_status()
raise
finally:
self.state.running = False
await self.write_status()
except Exception as e:
self.state.record_error(str(e))
await self.write_status()
raise
finally:
self.state.running = False
await self.write_status()
async def write_status(self):
"""Write current state to status file"""
@@ -124,31 +177,21 @@ class WatchService:
# Update stats
for path in report.new:
event = self.state.add_event(
self.state.add_event(
path=path, action="new", status="success", checksum=report.checksums[path]
)
console.print(
f"{event.timestamp.isoformat(timespec='minutes')} New:\t\t [green]{path}[/green] ({event.checksum[:8]})"
)
for path in report.modified:
event = self.state.add_event(
self.state.add_event(
path=path, action="modified", status="success", checksum=report.checksums[path]
)
console.print(
f"{event.timestamp.isoformat(timespec='minutes')} Modified:\t [yellow]{path}[/yellow] ({event.checksum[:8]})"
)
for old_path, new_path in report.moves.items():
event = self.state.add_event(
self.state.add_event(
path=f"{old_path} -> {new_path}",
action="moved",
status="success",
checksum=report.checksums[new_path],
)
console.print(
f"{event.timestamp.isoformat(timespec='minutes')} Moved:\t\t [blue]{old_path} -> {new_path}[/blue] ({event.checksum[:8]})"
)
for path in report.deleted:
event = self.state.add_event(path=path, action="deleted", status="success")
console.print(f"{event.timestamp.isoformat(timespec='minutes')} Deleted:\t [red]{path}[/red]")
self.state.add_event(path=path, action="deleted", status="success")
await self.write_status()