Skip to content

Cron job

Area: operasional. Pekerja latar belakang lintas modul, bukan satu modul. Mereka harus dijadwalkan di server lewat crontab sistem. Mereka ada di direktori top-level cron/ sebagai skrip PHP mandiri yang dijalankan daemon cron OS, tidak pernah dari UI aplikasi.

Cara halaman ini diverifikasi

Daftar direktori dibaca di branch produksi masing-masing big five pada 2026-09-16. Job Multiple Sign Off dibaca di master pada commit INA01-866 e230a25be dan c63dd6658, yang saat halaman ini ditulis masih lokal dan belum ada di origin/main. Job lain dibaca di master pada 2026-09-06.

Beberapa job memanggil endpoint HTTP di dalam aplikasi dengan cURL, jadi base URL aplikasi ($inweb_baseurl, baris baseurl di inweb_config) harus bisa dijangkau dari server itu sendiri dan TLS harus berfungsi. Panggilan ini menonaktifkan SSL_VERIFYPEER.

Crontab produksi minimal

README.md master memasang dua entri pertama. Job Multiple Sign Off diperlukan di mana pun pengguna men-sign off beberapa routing sekaligus. Dua terakhir adalah job notifikasi yang dijaga config.

text
# setiap menit — kirim antrean email keluar (SMTP lewat PHPMailer)
* * * * * php /path/to/app/cron/inact_mailgun_curl.php >> /dev/null 2>&1

# setiap menit — antrean submission procurement
* * * * * php /path/to/app/cron/cron_submit_queue.php >> /dev/null 2>&1

# setiap menit — selesaikan Multiple Sign Off (dokumen approved, transmittal, publish library)
* * * * * php /path/to/app/cron/cron_multiple_signoff_v2.php >> /var/log/inact_multisignoff.log 2>&1

# setiap jam — digest routing (hanya bertindak saat enable_routing_notif_digest=1)
0 * * * * php /path/to/app/cron/inact_routing_digest.php

# harian — notifikasi routing overdue / akan jatuh tempo
0 7 * * * php /path/to/app/cron/cron_overdue_mail.php

Sesuaikan binary PHP dan path per environment dan arahkan output ke log supaya kegagalan terlihat. Aktifkan cron retention dan digest hanya kalau feature flag-nya menyala. Tidak ada baris crontab yang dipasang oleh deploy: skrip deploy/ master dan .github/workflows/deploy.yml tidak menyentuh cron. Setiap baris di atas adalah langkah manual di setiap server. Crontab produksi milik klien, lihat masing-masing halaman instance.

Job-job-nya

1. inact_mailgun_curl.php memanggil inact_mailgun2.php: antrean email keluar, setiap menit

Semua email keluar diantrekan ke ts_email; tidak ada yang dikirim sinkron. Pembungkus memanggil inact_mailgun2.php, yang memilih baris tertunda (ts_email WHERE email_sent='n', yang terlama dulu, ukuran batch dari EMAIL_TOTAL_PER_BATCH), menandainya 'q', dan mengirim masing-masing lewat SMTP (PHPMailer) memakai setting $inweb_smtp_*. Saat berhasil email_sent='y' plus stempel waktu kirim; saat gagal 'e'. Menghormati kuota harian (EMAIL_QUOTA_PER_DAY, -1 = tanpa batas). Meski namanya "mailgun", pengirimannya lewat SMTP.

  • Tabel: ts_email (email_sent: n, lalu q, lalu y atau e).
  • Config: key .env EMAIL_QUOTA_PER_DAY (default -1) dan EMAIL_TOTAL_PER_BATCH (default 10), dibaca dengan $_ENV[...] ?? default di inact_mailgun2.php. Keduanya tidak ada di file env contoh; set hanya untuk mengubah default.
  • Kalau tidak berjalan: tidak ada email yang pernah terkirim. Setiap notifikasi menumpuk tak terkirim.

Pembungkus menargetkan inact_mailgun2.php di kelima fork.

2. cron_multiple_signoff_v2.php: menyelesaikan Multiple Sign Off, setiap menit

Multiple Sign Off mencatat semua sign off sekaligus, lalu mengantrekan pekerjaan yang lambat di ts_multiple_signoff_list, satu baris per performer yang sign off (rout_id, map_id). Job ini mengerjakan pekerjaan lambat itu. Ini versi master sejak INA01-866; cron_multiple_signoff.php, cron_create_routing_slip.php dan getPDFMultipleSignoffCron.php yang lama sudah dihapus dari master.

Performer yang sign offYang dijalankan jobHasil
Di bagian Document Controller dari routing (D - Transmit)publishTransmitSignOff()Record Document Library, Transmittal keluar saat issued status external dan enable_transmittal = 1, folder library. Satu transaksi DB.
Selain itu (A - Approval, C / S yang me-reject, I - Information terakhir)finishApprovalSignOff()curl ke getPDFAfterApprove.php (dokumen _R), Transmittal return saat external dan enable_transmittal = 1, folder library setelah sign off yang approved
  • Batch: 10 baris, multi_id terlama dulu, hanya multi_status = 'n', cron_ongoing 'n' atau NULL, dan map_id tidak NULL.
  • Klaim: tiap baris diset cron_ongoing = 'y' sebelum pekerjaannya dimulai. Berhasil mengeset multi_status = 'y', cron_ongoing = 'n'. Exception atau PHP Error apa pun mengeset keduanya kembali ke 'n', jadi baris dicoba lagi menit berikutnya. Tidak ada batas percobaan ulang.
  • Setiap baris diklaim sendiri, dengan satu UPDATE bersyarat yang hanya cocok untuk baris yang masih bebas. Dua eksekusi yang tumpang tindih tidak pernah mengambil baris yang sama, jadi tidak perlu lock file atau flock. Baris yang dilewati mencetak queue row 12: taken by another run, skipped.
  • Setiap baris dijalankan atas nama performer yang sign off (getSignOffPerformer()), jadi author dokumen dan log menunjukkan orang itu, bukan user sistem.
  • Flag: publish butuh enable_autopublish = 1; dokumen _R untuk A juga butuh flag itu. I - Information selalu membangun dokumennya.
  • Kalau tidak berjalan: sign off tercatat dan routing tertutup, tetapi dokumen _R approved, Transmittal dan record Document Library tidak muncul. Baris menumpuk di multi_status = 'n'.
  • Detail: Multiple Sign Off.

3. inact_routing_digest.php: digest routing, setiap jam, dijaga flag

Saat enable_routing_notif_digest='1', routing_notif_digest_hour tidak kosong, dan jam saat ini ada di CSV itu, ia mengelompokkan baris ts_map_routing_to yang masih terbuka per project dan penerima dan mengirim satu email digest gabungan per pengguna, diantrekan lewat ts_email.

  • Config: enable_routing_notif_digest, routing_notif_digest_hour, lihat inweb_config.
  • Kalau flag-nya mati: langsung keluar.
  • Ada di: master, Jadestone, Medco. Tidak di JOTRE atau Prima Energy.

4. inact_routing_overdue_digest.php: digest overdue, dijaga flag

Membaca enable_routing_overdue_notif_digest langsung dari inweb_config dan, saat menyala, mengirim digest item overdue. Hanya ada di master dan Jadestone; key-nya hanya ada di seed mereka.

5. cron_overdue_mail.php: notifikasi overdue dan akan jatuh tempo, harian

Mengirim pemberitahuan "overdue" dan "due soon" per penerima untuk routing yang mendekati atau melewati rout_due_date, menghormati hari kerja dan libur. Jendela pandang ke depan adalah key .env NOTIF_OVERDUE_SINCE_DAY (1 = peringatan satu hari sebelumnya, default saat kosong; 0 = hari ini; negatif = sudah lewat). Ada di kelima fork.

Menyiapkan cron Multiple Sign Off

Lakukan ini di setiap server yang menjalankan master setelah INA01-866: dev, staging dan produksi. Deploy tidak melakukannya untuk Anda.

1. Periksa prasyarat

PeriksaKenapaCara memeriksa
Migrasi 20260915090000_alter_ts_multiple_signoff_list_add_map_id sudah jalanJob membaca ts_multiple_signoff_list.map_idDeploy dev dan staging menjalankan phinx migrate sendiri. Produksi perlu dijalankan manual: php vendor/bin/phinx migrate
PHP CLI, bukan PHP-FPMSkrip langsung keluar, tanpa output, di SAPI lain (PHP_SAPI !== 'cli')php -v
PHP CLI memuat extension yang sama dengan PHP websetting.php memuat class Composer, membuat client MongoDB dan butuh curlphp -m lalu bandingkan dengan phpinfo() web
.env aplikasi ada di root aplikasisetting.php memuat .env dari root aplikasi. Skrip pindah ke direktori itu sendiri, jadi crontab tidak perlu cdls /path/to/app/.env
baseurl di inweb_config bisa dijangkau dari server itu sendirifinishApprovalSignOff() memanggil <baseurl>/includes/javascripts/tracking/pdfviewer/web/api/getPDFAfterApprove.php, timeout 600 detik, SSL verify matiLihat perintah curl di bawah
MongoDB bisa dijangkauSetiap penulisan yang di-log ($pdo->log()) meng-insert ke collection inweb_logs. Insert yang gagal ditangkap dan dikirim ke log error PHP, jadi tidak menghentikan jobKey MONGO_* di .env
User cron bisa menulis folder uploadPDF Transmittal ditulis di bawah docUpload/transmittalJalankan job sekali sebagai user itu (langkah 3)

Pastikan base URL menjawab dari server. Pertama baca nilainya dari database:

sql
SELECT config_value FROM inweb_config WHERE config_name = 'baseurl';

Lalu panggil halamannya dari server, dengan nilai itu menggantikan <baseurl>:

bash
curl -k -s -o /dev/null -w '%{http_code}\n' "<baseurl>/includes/javascripts/tracking/pdfviewer/web/api/getPDFAfterApprove.php"

Kode HTTP apa pun di bawah 400 berarti baik. Job menganggap error curl atau kode HTTP 400 ke atas sebagai kegagalan.

2. Pasang barisnya dan hapus yang lama

Di Linux dan macOS, tambahkan baris dengan crontab -e sebagai user pemilik file aplikasi:

text
* * * * * php /path/to/app/cron/cron_multiple_signoff_v2.php >> /var/log/inact_multisignoff.log 2>&1

Tanpa lock file dan tanpa flock. Setiap baris antrean diklaim dengan satu UPDATE bersyarat, jadi dua eksekusi yang tumpang tindih tidak pernah mengambil baris yang sama. Karena itu juga barisnya sama saja di Windows.

Di Windows (Tomori jalan di IIS) tidak ada crontab. Buat task Task Scheduler yang berulang tiap menit dan menjalankan perintah yang sama. Path Tomori, dari halaman instance-nya: PHP ada di C:\php\php.exe dan aplikasinya di C:\inetpub\wwwroot\inact, jadi program-nya C:\php\php.exe dan argumennya C:\inetpub\wwwroot\inact\cron\cron_multiple_signoff_v2.php.

TODO: setelan Task Scheduler persisnya untuk job ini di server Windows — nama task, akun yang menjalankannya, dan ke mana output-nya ditulis — belum terdokumentasi di mana pun.

Hapus baris cron_multiple_signoff.php kalau ada (job v1). File-nya sudah tidak ada di master, jadi baris itu hanya mengisi mail cron atau log dengan error. Pastikan file log bisa ditulis oleh user itu.

3. Jalankan sekali secara manual

bash
php /path/to/app/cron/cron_multiple_signoff_v2.php

4. Pastikan job berjalan

Pantau log-nya:

bash
tail -f /var/log/inact_multisignoff.log

Yang dicetak job, diambil dari skripnya:

BarisArti
multiple sign off queue is emptySehat, tidak ada yang dikerjakan. Dicetak sekali per menit saat menganggur
multiple sign off queue: 3 row(s)Satu batch dibaca
queue row 12: taken by another run, skippedBaris itu sudah diklaim eksekusi lain. Tidak masalah
routing 120 (map 845): publish lalu published as doc no 9031Baris D - Transmit. nothing to publish berarti enable_autopublish mati atau routing tidak punya file dokumen
routing 121 (map 850): approved documentBaris A / C / S / I, curl ke getPDFAfterApprove.php
doneBaris selesai (multi_status = 'y')
WARNING: return transmittal failed: ...Transmittal return gagal, tetapi baris tetap ditandai selesai, sama seperti Sign Off tunggal
ERROR: ...Baris kembali ke 'n' dan jalan lagi menit berikutnya
doneAkhir batch
ERROR: cannot read ts_multiple_signoff_list: ..., atau PDOException yang tidak ditangkapQuery antrean gagal. Biasanya migrasi belum jalan, jadi map_id belum ada

Periksa antrean di database (SQL portabel):

sql
SELECT multi_id, rout_id, map_id, multi_status, cron_ongoing FROM ts_multiple_signoff_list WHERE multi_status = 'n' ORDER BY multi_id;

Sehat: baris yang map_id-nya terisi keluar dari daftar ini dalam satu atau dua menit setelah Multiple Sign Off.

5. Bersihkan klaim yang macet

Eksekusi yang terbunuh di tengah jalan (fatal error PHP, kehabisan memori, server restart) meninggalkan barisnya di cron_ongoing = 'y', dan eksekusi berikutnya melewatinya. Pastikan dulu tidak ada eksekusi yang aktif (pgrep -f cron_multiple_signoff_v2.php tidak mencetak apa-apa), lalu:

sql
UPDATE ts_multiple_signoff_list SET cron_ongoing = 'n' WHERE multi_status = 'n' AND cron_ongoing = 'y';

Troubleshooting

GejalaPenyebabPerbaikan
Log menampilkan ERROR: getPDFAfterApprove failed: ... setiap menit, baris tetap di nbaseurl tidak terjangkau dari server (DNS, firewall, URL publik yang tidak bisa diakses balik), atau halaman mengembalikan HTTP 400 ke atasJalankan cek curl di langkah 1. Perbaiki DNS / hosts atau inweb_config.baseurl
Log kosong sama sekaliBaris belum dipasang, path log tidak bisa ditulis, atau PHP bukan binary CLIcrontab -l, cek pemilik file log, php -v
Baris tetap di n dengan cron_ongoing = 'y'Eksekusi terbunuh di tengah jalanLangkah 5
Baris tetap di n dengan map_id NULLBaris lama yang ditulis sebelum INA01-866. Job sengaja melewatinyaPeriksa tiap routing secara manual, lalu set multi_status = 'y'
ERROR: cannot read ts_multiple_signoff_list atau PDOException tentang map_idMigrasi belum jalanJalankan phinx migrate. Sampai itu, setiap Multiple Sign Off di browser juga gagal dengan "Sign off failed"
ERROR: performer row N not foundBaris performer dihapus setelah sign offPeriksa routing-nya, lalu set baris ke multi_status = 'y'
Antrean terkuras tetapi routing A tidak dapat dokumen _Renable_autopublish mati. Job lalu hanya membuat Transmittal return (saat external dan enable_transmittal = 1)Memang begitu. Nyalakan flag hanya kalau instance memang harus publish
Satu eksekusi lebih lama dari satu menit dan eksekusi berikutnya mulaiWajar. Setiap baris diklaim sendiri, jadi eksekusi kedua hanya mengambil baris yang belum diambilTidak perlu apa-apa

TODO: setelah timeout curl (600 detik) baris dicoba ulang, tetapi request web mungkin tetap selesai di server. Apakah percobaan ulang bisa membangun dokumen _R dua kali belum diperiksa.

TODO: publish D - Transmit yang gagal me-rollback database, tetapi PDF Transmittal yang sudah ditulis ke docUpload/transmittal tetap ada di disk. Apakah file itu dibersihkan di tempat lain belum diperiksa.

Sisa isi cron/

Master menyimpan 18 file. Di luar lima di atas:

SkripTujuanDijaga olehAda di
inact_doclib_retention.phpMenandai dan memberi tahu dokumen yang mendekati retensi atau kedaluwarsaenable_doclib_retentionmaster, Jadestone, Medco, JOTRE
inact_direct_update_data.phpPemeliharaan super-admin, memperbaiki penanda inbox routing yang basihanya super-adminkelima fork
cron_bypass_overdue.phpPenanganan bypass overduekelima fork
cron_create_routing_slip.phpMembuat routing slip untuk cron multiple sign-off lamaJadestone, Medco, JOTRE, Prima Energy. Dihapus dari master oleh INA01-866
cron_issue_staging_oversize.phpEmail tentang ukuran file dokumen staging. Bukan konverter halaman berukuran besar.kelima fork
cron_submit_queue.php, procurement_submit_attachment.php, pl_submit_attachment.phpAntrean submission dan lampiran procurement dan packing-listkelima fork
expediting_weekly_cron.phpJob expediting mingguan (procurement)kelima fork
cron_dump_db.phpDump database terjadwalkelima fork
cron_delete_empty_emailto.phpPembersihan emailkelima fork
cron_pool_idapd.phpMengirim email; tujuannya tidak didokumentasikan di filekelima fork
setting.phpBootstrap bersama untuk skrip-skrip, bukan jobkelima fork

TODO: untuk apa cron_pool_idapd.php.

Catatan operasional dan hal yang perlu diwaspadai

  • Email sepenuhnya asinkron. Semuanya lewat ts_email dan job 1. Job digest dan overdue juga mengantre ke ts_email, jadi job 1 tetap kritis.
  • Ketergantungan cURL. Job 1 dan separuh A / C / S / I dari job 2 memanggil balik aplikasi lewat HTTP. $inweb_baseurl yang salah atau tidak terjangkau membuat job 1 diam-diam tidak berbuat apa-apa, dan membuat job 2 mencoba baris yang sama setiap menit.
  • Cron yang dijaga flag diam saja saat mati. inact_routing_digest.php, inact_routing_overdue_digest.php dan inact_doclib_retention.php keluar lebih awal kecuali feature flag-nya diset. Mudah dikira "rusak".
  • Job Multiple Sign Off yang menganggur tetap menulis satu baris log per menit. Lakukan rotasi /var/log/inact_multisignoff.log.

Perbedaan antar instance

Diperiksa pada 2026-09-16 di origin/main masing-masing fork. Master dihitung setelah INA01-866.

InstanceCron Multiple Sign OffPerbedaan lain
Master (setelah INA01-866)hanya cron_multiple_signoff_v2.php18 file
Jadestonecron_multiple_signoff.php dan cron_multiple_signoff_v2.php, plus cron_create_routing_slip.php. v2-nya versi sendiri, bukan file master20 file
Medcocron_multiple_signoff_v2.php (versi sendiri), cron_create_routing_slip.php dan cron_create_routing_slip_old.php21 file. cron_daily_summary.php masih ada, plus inact_archive_mail.php. Tidak ada inact_routing_overdue_digest.php.
JOTREcron_multiple_signoff.php (v1) dan cron_create_routing_slip.php32 file. Menambah dua belas skrip accurate_* (sinkronisasi dan backfill ke sistem akuntansi Accurate) dan backfill_expediting_chain.php, backfill_mrr_no.php. Tidak ada cron digest.
Prima Energycron_multiple_signoff.php (v1) dan cron_create_routing_slip.php16 file. Tidak ada inact_doclib_retention.php, tidak ada cron digest.

TODO: file mana yang dijadwalkan server Jadestone, v1 atau v2, saat keduanya ada.

Terkait

  • Multiple Sign Off mengisi antrean ts_multiple_signoff_list yang dikuras job 2.
  • Sign Off: sign off tunggal yang ditiru job ini.
  • inweb_config mencantumkan flag yang menjaga cron digest dan retention.