initial commit — dropLake
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
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
|
||||
Reference in New Issue
Block a user