Hallo Stroke

Backend Reminders

The pengingat scheduler — type-specific matching, timezone handling, and dispatch.

The reminder engine is the richest domain logic in the backend. A background goroutine (startPengingatScheduler) ticks every 20 seconds and calls pengingatService.CheckAndSendPengingatBySchedule().

Schedule matching by type

Loading diagram...

obat (medicine)

  • Reads the jadwal array from JSONB details.
  • Compares each jam_original (user's input time) against current time in the user's timezone, with a 30-second tolerance.
  • Tracks per-schedule send state via a sent_schedules map in details so a single reminder row holds multiple daily dose times (e.g. 08:00 + 20:00) and fires each independently.
  • Marks IsSent = true only when all schedules are sent.

makan (meal)

  • Same pattern, tracks matched_meal_schedule_key (meal_<idx>_<time>) and a sent_meal_schedules map.
  • Each meal slot fires once; fully sent only when every schedule is consumed.

terapi (therapy)

  • Matches both day of week (Indonesian names: Senin/Selasa/...) and HH:mm time against the jadwal array. Weekly recurring.

kontrol (consultation)

  • Matches a full datetime (2006-01-02 15:04) — one-shot appointment reminder.

default

  • Time-only match against pengingat.Waktu.

Timezone handling

All times are stored as UTC in the database. User-supplied times are converted to UTC at create time using the timezone field (default Asia/Makassar, WITA). On send, the service converts back to the user's timezone for the message body. The jam_original field preserves the user's literal input for matching.

Dispatch

For each matched schedule, the service:

  1. Builds a PengingatDTO.
  2. Calls notificationService.SendPengingatViaWhatsapp (WhatsApp).
  3. Calls pushService.SendReminderNotification (web push).
  4. Persists updated sent_schedules / IsSent back via repo.Update.

WhatsApp message formatting

whatsapp/service.go SendPengingatViaWhatsapp constructs Bahasa Indonesia messages per type:

TypeMessage includes
obat"waktunya minum obat" + drug name
terapitempat_terapi, jenis_terapi, time
kontroldoctor name, specialization, facility, date
makansuggested karbohidrat/protein/lemak/vitamin/serat menu
default"Judul/Tanggal/Waktu" format

Per-schedule state

The clever bit: instead of one row per dose time, a single pengingats row carries the whole day's schedule in JSONB and the scheduler mutates a sent_schedules map to remember which slots already fired. This keeps the reminder list compact and the "all done" check trivial.

On this page