a357e0622e
Single DAG, single 30-min schedule instead of 5-min or two separate DAGs. run_sync() itself decides whether to do real work: always during business hours (default 07:00-17:00 WIB), otherwise only once per EDOXID_OFF_HOURS_INTERVAL_MINUTES (default 120) tracked via a last_full_sync timestamp in the sqlite state. Off-hours skips return immediately without touching DB/Calendar/Gmail at all.
70 lines
3.1 KiB
Python
70 lines
3.1 KiB
Python
"""
|
|
DAG: sync jadwal sidang eDOXID -> Google Calendar "Jadwal Sidang" + reminder email.
|
|
|
|
DAG ini trigger tiap 30 menit sepanjang hari (1 DAG, 1 schedule — bukan 2 DAG
|
|
terpisah untuk jam-kerja/luar-jam-kerja, biar sederhana), tapi `run_sync()`
|
|
sendiri yang memutuskan kerja BENERAN atau skip:
|
|
- Jam kerja (default 07:00-17:00 WIB, EDOXID_BUSINESS_HOURS_START/END): tiap
|
|
trigger (~30 menit) langsung kerja penuh.
|
|
- Di luar jam kerja: cuma kerja penuh kalau sudah >=
|
|
EDOXID_OFF_HOURS_INTERVAL_MINUTES (default 120 menit) sejak sync terakhir;
|
|
kalau belum, skip (tidak buka koneksi DB/Calendar/Gmail sama sekali, murah).
|
|
Alasan: 30 menit sepanjang hari dianggap kurang efisien (bukan soal Google
|
|
menganggap ini "bot" — ini OAuth API resmi dengan izin, bukan scraping —
|
|
tapi soal efisiensi jumlah run), tapi tetap ingin responsif di jam kerja.
|
|
|
|
Kerja penuh artinya:
|
|
1. create/update/delete event Google Calendar sesuai jadwal sidang yang
|
|
baru/berubah/dibatalkan.
|
|
2. Kirim email reminder terpisah (subjek "[PENGINGAT SEBELUM H-1]" dan
|
|
"[PENGINGAT 1 JAM SEBELUM]") ke semua attendee (mahasiswa+pembimbing+penguji)
|
|
pas jam H-1 07:00 dan 1 jam sebelum sidang — karena reminders.overrides
|
|
bawaan Calendar API cuma berlaku untuk kalender pemilik event (TU), TIDAK
|
|
ikut ke kalender pribadi tiap attendee (keterbatasan Google Calendar,
|
|
dikonfirmasi 2026-07-27).
|
|
|
|
Auth Google pakai OAuth refresh token sebagai tu@informatika.untan.ac.id
|
|
langsung (bukan service account — service account tidak bisa invite attendee
|
|
tanpa Domain-Wide Delegation, sudah dicoba dan ditolak Google 2026-07-27).
|
|
Refresh token perlu scope gabungan: calendar + gmail.send.
|
|
|
|
Tidak menyentuh kode/DB aplikasi eDOXID (`/var/www/manajemen-usulan`) sama
|
|
sekali selain query SELECT read-only ke 3 tabel: submissions, verificators, users.
|
|
|
|
Environment yang wajib di-set di Coolify (service airflow-scheduler):
|
|
EDOXID_DB_PASSWORD
|
|
EDOXID_GOOGLE_CLIENT_ID, EDOXID_GOOGLE_CLIENT_SECRET, EDOXID_GOOGLE_REFRESH_TOKEN
|
|
(refresh token WAJIB scope "calendar" + "gmail.send" sekaligus, bukan cuma calendar)
|
|
Opsional (lihat scripts/edoxid_calendar_config.py untuk default):
|
|
EDOXID_DB_HOST, EDOXID_DB_PORT, EDOXID_DB_DATABASE, EDOXID_DB_USERNAME,
|
|
EDOXID_GOOGLE_CALENDAR_ID, EDOXID_STATE_SQLITE_PATH, EDOXID_SYNC_MIN_DATE,
|
|
EDOXID_BUSINESS_HOURS_START (default 7), EDOXID_BUSINESS_HOURS_END (default 17),
|
|
EDOXID_OFF_HOURS_INTERVAL_MINUTES (default 120)
|
|
"""
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from airflow import DAG
|
|
from airflow.operators.python import PythonOperator
|
|
|
|
from scripts.edoxid_calendar_sync import run_sync
|
|
|
|
with DAG(
|
|
dag_id="edoxid_calendar_sync",
|
|
description="Sync jadwal sidang eDOXID ke Google Calendar 'Jadwal Sidang'",
|
|
start_date=datetime(2026, 7, 27),
|
|
schedule_interval="*/30 * * * *",
|
|
catchup=False,
|
|
max_active_runs=1,
|
|
default_args={
|
|
"owner": "informatika",
|
|
"retries": 1,
|
|
"retry_delay": timedelta(minutes=1),
|
|
},
|
|
tags=["edoxid", "calendar", "sidang"],
|
|
) as dag:
|
|
sync_task = PythonOperator(
|
|
task_id="sync_jadwal_sidang",
|
|
python_callable=run_sync,
|
|
)
|