somratpro Claude Sonnet 4.6 commited on
Commit
08569ac
Β·
1 Parent(s): fd8bbbe

fix backup status display, sync loop safety, and startup log noise

Browse files

- paperclip-sync.py: write explicit status+message fields in sync_to_backup
and sync_from_backup (previously relied on compat shim which mapped
last_error→message, causing empty message on success and duplicate
"Last sync" lines in dashboard)
- paperclip-sync.py: change log format to [sync] %(message)s (drop verbose
timestamp/level prefix that cluttered startup restore output)
- start.sh: sanitize SYNC_INTERVAL (strip non-digits, clamp β‰₯60s) to
prevent sleep "" failure causing tight spin loop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. paperclip-sync.py +19 -6
  2. start.sh +4 -1
paperclip-sync.py CHANGED
@@ -32,7 +32,7 @@ huggingface_hub.utils.disable_progress_bars()
32
  # Logging: WARNING level keeps errors visible, suppresses routine INFO chatter
33
  logging.basicConfig(
34
  level=logging.WARNING,
35
- format='%(asctime)s - %(levelname)s - %(message)s'
36
  )
37
  logger = logging.getLogger(__name__)
38
  # Set our own logger to INFO so backup/restore start+finish lines still print
@@ -490,16 +490,16 @@ def sync_to_backup() -> bool:
490
  # Step 1: Backup database
491
  dump_file, success = backup_database()
492
  if not success or not dump_file:
493
- status['last_error'] = 'Database backup failed'
494
- status['db_status'] = 'error'
495
  write_status(status)
496
  return False
497
 
498
  # Step 2: Create tarball
499
  tarball_file, success = create_backup_tarball(dump_file)
500
  if not success or not tarball_file:
501
- status['last_error'] = 'Tarball creation failed'
502
- status['db_status'] = 'error'
503
  write_status(status)
504
  return False
505
 
@@ -507,10 +507,13 @@ def sync_to_backup() -> bool:
507
  success = sync_to_hf(tarball_file)
508
 
509
  # Update status
510
- status['last_sync_time'] = datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
 
511
  status['db_status'] = 'connected' if success else 'error'
512
  status['last_error'] = None if success else 'Upload failed'
513
  status['sync_count'] = status.get('sync_count', 0) + 1
 
 
514
 
515
  write_status(status)
516
 
@@ -526,6 +529,8 @@ def sync_to_backup() -> bool:
526
  logger.error(f'Backup operation failed: {e}')
527
  status['last_error'] = str(e)
528
  status['db_status'] = 'error'
 
 
529
  write_status(status)
530
  return False
531
 
@@ -542,18 +547,24 @@ def sync_from_backup() -> bool:
542
  # No backup exists yet (first boot) β€” not an error
543
  status['db_status'] = 'connected'
544
  status['last_error'] = None
 
 
545
  write_status(status)
546
  logger.info('No prior backup β€” fresh instance')
547
  return True
548
  elif success:
549
  status['db_status'] = 'connected'
550
  status['last_error'] = None
 
 
551
  write_status(status)
552
  logger.info('Restore OK')
553
  return True
554
  else:
555
  status['db_status'] = 'error'
556
  status['last_error'] = 'Restore failed'
 
 
557
  write_status(status)
558
  logger.warning('Restore operation failed')
559
  return False
@@ -562,6 +573,8 @@ def sync_from_backup() -> bool:
562
  logger.error(f'Restore operation failed: {e}')
563
  status['last_error'] = str(e)
564
  status['db_status'] = 'error'
 
 
565
  write_status(status)
566
  return False
567
 
 
32
  # Logging: WARNING level keeps errors visible, suppresses routine INFO chatter
33
  logging.basicConfig(
34
  level=logging.WARNING,
35
+ format='[sync] %(message)s'
36
  )
37
  logger = logging.getLogger(__name__)
38
  # Set our own logger to INFO so backup/restore start+finish lines still print
 
490
  # Step 1: Backup database
491
  dump_file, success = backup_database()
492
  if not success or not dump_file:
493
+ status.update({'last_error': 'Database backup failed', 'db_status': 'error',
494
+ 'status': 'error', 'message': 'Backup failed: pg_dump error'})
495
  write_status(status)
496
  return False
497
 
498
  # Step 2: Create tarball
499
  tarball_file, success = create_backup_tarball(dump_file)
500
  if not success or not tarball_file:
501
+ status.update({'last_error': 'Tarball creation failed', 'db_status': 'error',
502
+ 'status': 'error', 'message': 'Backup failed: tarball too large or I/O error'})
503
  write_status(status)
504
  return False
505
 
 
507
  success = sync_to_hf(tarball_file)
508
 
509
  # Update status
510
+ ts = datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
511
+ status['last_sync_time'] = ts
512
  status['db_status'] = 'connected' if success else 'error'
513
  status['last_error'] = None if success else 'Upload failed'
514
  status['sync_count'] = status.get('sync_count', 0) + 1
515
+ status['status'] = 'success' if success else 'error'
516
+ status['message'] = 'Backup uploaded to HF Dataset' if success else 'Upload to HF Dataset failed'
517
 
518
  write_status(status)
519
 
 
529
  logger.error(f'Backup operation failed: {e}')
530
  status['last_error'] = str(e)
531
  status['db_status'] = 'error'
532
+ status['status'] = 'error'
533
+ status['message'] = f'Backup error: {e}'
534
  write_status(status)
535
  return False
536
 
 
547
  # No backup exists yet (first boot) β€” not an error
548
  status['db_status'] = 'connected'
549
  status['last_error'] = None
550
+ status['status'] = 'configured'
551
+ status['message'] = 'Fresh instance β€” no prior backup'
552
  write_status(status)
553
  logger.info('No prior backup β€” fresh instance')
554
  return True
555
  elif success:
556
  status['db_status'] = 'connected'
557
  status['last_error'] = None
558
+ status['status'] = 'restored'
559
+ status['message'] = 'Restored from HF Dataset'
560
  write_status(status)
561
  logger.info('Restore OK')
562
  return True
563
  else:
564
  status['db_status'] = 'error'
565
  status['last_error'] = 'Restore failed'
566
+ status['status'] = 'error'
567
+ status['message'] = 'Restore from HF Dataset failed'
568
  write_status(status)
569
  logger.warning('Restore operation failed')
570
  return False
 
573
  logger.error(f'Restore operation failed: {e}')
574
  status['last_error'] = str(e)
575
  status['db_status'] = 'error'
576
+ status['status'] = 'error'
577
+ status['message'] = f'Restore error: {e}'
578
  write_status(status)
579
  return False
580
 
start.sh CHANGED
@@ -17,7 +17,10 @@ export PAPERCLIP_CONFIG="${PAPERCLIP_CONFIG:-${PAPERCLIP_HOME}/instances/default
17
  export PAPERCLIP_TELEMETRY_DISABLED="${PAPERCLIP_TELEMETRY_DISABLED:-1}"
18
  export DO_NOT_TRACK="${DO_NOT_TRACK:-1}"
19
  export OPENCODE_ALLOW_ALL_MODELS="${OPENCODE_ALLOW_ALL_MODELS:-true}"
20
- export SYNC_INTERVAL="${SYNC_INTERVAL:-3600}"
 
 
 
21
  export SYNC_MAX_FILE_BYTES="${SYNC_MAX_FILE_BYTES:-52428800}"
22
  export BACKUP_DATASET_NAME="${BACKUP_DATASET_NAME:-huggingclip-backup}"
23
 
 
17
  export PAPERCLIP_TELEMETRY_DISABLED="${PAPERCLIP_TELEMETRY_DISABLED:-1}"
18
  export DO_NOT_TRACK="${DO_NOT_TRACK:-1}"
19
  export OPENCODE_ALLOW_ALL_MODELS="${OPENCODE_ALLOW_ALL_MODELS:-true}"
20
+ # Sanitize: strip non-digits, clamp minimum to 60s to prevent spin loops.
21
+ SYNC_INTERVAL=$(printf '%s' "${SYNC_INTERVAL:-3600}" | tr -dc '0-9')
22
+ { [ -z "${SYNC_INTERVAL}" ] || [ "${SYNC_INTERVAL}" -lt 60 ]; } && SYNC_INTERVAL=3600
23
+ export SYNC_INTERVAL
24
  export SYNC_MAX_FILE_BYTES="${SYNC_MAX_FILE_BYTES:-52428800}"
25
  export BACKUP_DATASET_NAME="${BACKUP_DATASET_NAME:-huggingclip-backup}"
26