64 lines
1.7 KiB
Python
64 lines
1.7 KiB
Python
import logging
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
|
from sqlalchemy.orm import Session
|
|
|
|
from config import settings
|
|
from database import SecurityEvent, SessionLocal, Share
|
|
|
|
log = logging.getLogger("droplake.cleanup")
|
|
|
|
|
|
def purge_expired():
|
|
db: Session = SessionLocal()
|
|
try:
|
|
now = datetime.utcnow()
|
|
|
|
# Expired shares
|
|
expired = db.query(Share).filter(Share.expires_at < now).all()
|
|
|
|
# Burn-after-read shares that have been downloaded
|
|
burnt = (
|
|
db.query(Share)
|
|
.filter(Share.burn_after_read.is_(True), Share.downloaded.is_(True))
|
|
.all()
|
|
)
|
|
|
|
# Deduplicate by id
|
|
seen = {}
|
|
for s in expired + burnt:
|
|
seen[s.id] = s
|
|
to_remove = list(seen.values())
|
|
|
|
for share in to_remove:
|
|
blob = Path(settings.storage_path) / share.storage_path
|
|
blob.unlink(missing_ok=True)
|
|
db.add(SecurityEvent(event_type="share_cleaned", share_id=share.id))
|
|
db.delete(share)
|
|
|
|
if to_remove:
|
|
db.commit()
|
|
log.info("Cleanup: removed %d share(s)", len(to_remove))
|
|
except Exception as exc:
|
|
log.error("Cleanup error: %s", exc)
|
|
db.rollback()
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
def start_scheduler() -> BackgroundScheduler:
|
|
scheduler = BackgroundScheduler(daemon=True)
|
|
scheduler.add_job(
|
|
purge_expired,
|
|
"interval",
|
|
minutes=settings.cleanup_interval_minutes,
|
|
id="cleanup",
|
|
replace_existing=True,
|
|
misfire_grace_time=60,
|
|
)
|
|
scheduler.start()
|
|
log.info("Cleanup scheduler started (every %dm)", settings.cleanup_interval_minutes)
|
|
return scheduler
|