"""Periodic checked snapshots. Keeps every snapshot; never deletes old backups.

Run under a supervisor for continuous use. --count 0 continues until interrupted.
A snapshot failure exits nonzero rather than silently extending the recovery gap.
"""
import argparse, json, math, os, time
from pathlib import Path
from operations import backup

def run(database,directory,interval=900,count=0):
    if not math.isfinite(interval) or interval<=0:raise ValueError('interval must be finite and positive')
    if not isinstance(count,int) or count<0:raise ValueError('count must be a nonnegative integer')
    directory=Path(directory)
    if directory.is_symlink():raise ValueError('Backup root cannot be a symlink')
    directory.mkdir(mode=0o700,parents=True,exist_ok=True)
    i=0
    while count==0 or i<count:
        target=directory/('snapshot-'+str(time.time_ns()))
        result=backup(database,target);i+=1
        print(json.dumps({'snapshot':str(target),'sha256':result['sha256'],'bytes':result['bytes'],'elapsed_seconds':result['elapsed_seconds']}),flush=True)
        if count and i>=count:break
        time.sleep(interval)
    return i
if __name__=='__main__':
    p=argparse.ArgumentParser(description=__doc__);p.add_argument('--db',required=True);p.add_argument('--out',required=True);p.add_argument('--interval',type=float,default=900);p.add_argument('--count',type=int,default=0);args=p.parse_args();os.umask(0o077)
    try:run(args.db,args.out,args.interval,args.count)
    except KeyboardInterrupt:pass
