54 lines
1.9 KiB
Python
54 lines
1.9 KiB
Python
"""Processo único dedicado à sincronização periódica dos feeds."""
|
|
|
|
import fcntl
|
|
import logging
|
|
import os
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from apscheduler.schedulers.blocking import BlockingScheduler
|
|
|
|
import database
|
|
import ics_sync
|
|
|
|
|
|
logging.basicConfig(level=os.environ.get('LOG_LEVEL', 'INFO'))
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def sync_due_feeds():
|
|
now = datetime.now(timezone.utc)
|
|
for feed in database.get_all_feeds():
|
|
last_synced = feed.get('last_attempted') or feed.get('last_synced')
|
|
requested = feed.get('sync_requested_at')
|
|
try:
|
|
last = datetime.fromisoformat(last_synced) if last_synced else None
|
|
if last and last.tzinfo is None:
|
|
last = last.replace(tzinfo=timezone.utc)
|
|
due = not last or last + timedelta(minutes=feed['sync_interval_minutes']) <= now
|
|
except (TypeError, ValueError):
|
|
due = True
|
|
if requested or due:
|
|
ics_sync.sync_feed(feed['id'])
|
|
|
|
|
|
def main():
|
|
database.configure(os.environ.get(
|
|
'DATABASE_PATH', os.path.join(os.path.dirname(__file__), 'calendario.db')
|
|
))
|
|
database.init_db()
|
|
lock_path = os.environ.get('SCHEDULER_LOCK_PATH', '/tmp/studycalendar-scheduler.lock')
|
|
lock_fd = os.open(lock_path, os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
|
|
lock_file = os.fdopen(lock_fd, 'w', encoding='ascii')
|
|
try:
|
|
fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
except BlockingIOError as exc:
|
|
raise RuntimeError('Outro scheduler já está ativo neste host.') from exc
|
|
scheduler = BlockingScheduler(timezone='America/Sao_Paulo')
|
|
scheduler.add_job(sync_due_feeds, 'interval', minutes=1, id='sync-feeds', max_instances=1,
|
|
coalesce=True, next_run_time=datetime.now(timezone.utc))
|
|
logger.info('Scheduler dedicado iniciado.')
|
|
scheduler.start()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|