Files
satusehat-worker/docs/Devplan.md
T
2026-07-29 06:38:42 +00:00

251 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🗺️ Development Plan (Roadmap)
**Project:** GoPrint Service General (`worker-satusehat`)
**Versi:** 1.0
**Tanggal:** 2026-05-13
Peta jalan terurut berdasarkan **dampak vs effort**. Setiap fase punya keluaran yang bisa dirilis berdiri sendiri.
---
## Phase 0 — Stabilisasi Production Saat Ini *(12 minggu)*
**Tujuan:** Service yang sekarang sudah jalan (REST + RBAC + KFA Puller) bebas bug kritikal.
### Langkah Stabilisasi
1. **Fix `satusehatClient = nil`** ([main.go:235](cmd/api/main.go#L235))
- Inisialisasi: `satusehatClient := satusehat.NewClient(cfg)` lalu pass ke `worker.NewManager`.
- *Acceptance:* `go run` tidak panic ketika `cfg.SatuSehat.Enabled = true`.
2. **Pindahkan kredensial worker login ke env**
- `WORKER_AUTH_EMAIL`, `WORKER_AUTH_PASSWORD` di `.env` + validation di `config.Validate()`.
- Hapus default hardcoded di [worker/auth.go:25-28](internal/worker/auth.go#L25-L28).
3. **Audit & bersihkan kode mati**
- Hapus `patient/migrator.go` jika tidak akan dipakai, atau pindahkan ke folder `archive/` + buang default password.
- Hilangkan `truncate()` duplikat: pindah ke `pkg/logger` atau `pkg/utils`.
4. **Endpoint `/metrics` Prometheus aktif**
- Tambahkan handler `promhttp.Handler()` di `routes.go`.
- Definisikan counter dasar: `worker_documents_processed_total`, `worker_rate_limit_hits_total`, `satusehat_token_refresh_total`.
5. **gRPC handler `PermissionHandler` di-uncomment**
- Tes via `grpcurl` ke `:9090`.
**Output:** Tag `v0.9.0-stable`.
---
## Phase 1 — Aktivasi Worker Klinis *(24 minggu)*
**Tujuan:** Sinkronisasi data obat & radiologi ke SatuSehat jalan otomatis 24/7.
### Langkah Aktivasi
1. **Aktifkan worker secara bertahap di [worker.go](internal/worker/worker.go)** dengan urutan dependensi:
1. `Encounter` (prasyarat referensi)
2. `Medication` (master kode obat lokal → KFA)
3. `MedicationRequest`
4. `MedicationDispense`
5. `ServiceRequest (Radiology)`
6. `ImagingStudy`
2. **Validasi end-to-end per worker:**
- Cek `sync_log` (status SUCCESS/FAILED/RATE_LIMITED).
- Pastikan FHIR ID kembali & tersimpan di mapping harian.
- Monitor log error rate ≤ 1% per jam selama 48 jam soak test.
3. **Rate-limit config dinamis** — pindahkan konstanta `rateLimitSleep` per worker ke `config.yaml`:
```yaml
satu_sehat:
worker:
medication: { rate_limit_sleep: 60s, poll_interval: 2s }
imagingstudy: { rate_limit_sleep: 60s, poll_interval: 2s }
```
4. **Sync Log Retention Policy**
- Tabel `sync_log` bisa membengkak — tambahkan TTL/archive job (retain 90 hari, archive ke S3/MinIO).
**Output:** Tag `v1.0.0` — release bridging klinis pertama.
---
## Phase 2 — Stateless Worker (Multi-Replica Ready) *(23 minggu)*
**Tujuan:** Mendukung deployment Kubernetes / multi-pod tanpa risiko race tracker.
### Langkah Refactor State
1. **Tabel `sync_tracker`**
```sql
CREATE TABLE sync_tracker (
module_name VARCHAR(64) PRIMARY KEY,
last_id BIGINT,
last_timestamp TIMESTAMP,
updated_at TIMESTAMP DEFAULT NOW()
);
```
- Implementasi via row-lock `SELECT ... FOR UPDATE SKIP LOCKED` (Postgres) sehingga hanya satu replica per modul.
2. **Refactor helper `readLastID()` / `writeTracker()`**
- Bikin abstraksi `TrackerStore` di `pkg/tracker/` (Interface: `Get`, `Set` per module name).
- Implementasi backend `FileTracker` (lama) & `DBTracker` (baru). Pilih via env `TRACKER_BACKEND=db|file`.
3. **Migrasi data tracker yang ada**
- Script one-shot: baca semua `*.txt` di `internal/worker/satusehat/*/last_*` & `internal/master/kfa/kfa_tracker.txt` → seed ke `sync_tracker`.
4. **Mapping FHIR ID → Redis hash atau tabel**
- `mapperdata/YYYY-MM/YYYY-MM-DD.txt` tidak cocok multi-pod. Pindah ke tabel `fhir_id_map(local_id, fhir_id, resource_type, created_at)`.
5. **Leader election sederhana untuk worker eksklusif**
- Gunakan Redis `SET key NX EX 60` sebagai *lease* untuk worker singleton (KFA Puller, dst).
**Output:** Tag `v1.1.0` — deployable di Kubernetes dengan ≥ 2 replica.
---
## Phase 3 — Event-Driven Architecture *(46 minggu)*
**Tujuan:** Mengurangi polling DB → reactive berdasarkan trigger SIMRS.
### Langkah Event-Driven
1. **PostgreSQL LISTEN/NOTIFY**
- Trigger pada tabel sumber (mis. `t_pesan_obat` AFTER INSERT) → `NOTIFY pesan_obat_new, NEW.id::text`.
- Worker `Medication` subscribe via `pq.NewListener` daripada polling per 2 detik.
- Fallback: tetap ada polling tiap N detik sebagai *catch-up* untuk event yang tertinggal.
2. **Kafka Producer (opsional, untuk multi-microservice)**
- Uncomment [main.go:111-113](cmd/api/main.go#L111-L113).
- Publish event `fhir.resource.synced` setelah pengiriman sukses untuk konsumsi service lain (audit, BI, dashboard).
- Library: `segmentio/kafka-go` (lightweight).
3. **Dead Letter Queue**
- Pesan yang gagal kirim 3× → masuk topik `fhir.dlq` untuk inspeksi manual.
4. **Webhook callback dari `service-satusehat`**
- Jika service downstream support webhook untuk async FHIR commit, langganan untuk update `sync_log.status` lebih cepat.
**Output:** Tag `v1.2.0`.
---
## Phase 4 — Worker Coverage Lengkap *(rolling, 1 resource / sprint)*
**Tujuan:** Mengisi 13 worker stub menjadi production-ready.
### Urutan Prioritas Worker (berdasarkan kebutuhan pelaporan SatuSehat)
1. `Condition` (diagnosa)
2. `Observation` (vital sign, lab)
3. `Procedure` (tindakan medis)
4. `DiagnosticReport` (laporan lab/radiologi)
5. `AllergyIntolerance`
6. `Immunization`
7. `Specimen` (lab)
8. `ClinicalImpression`
9. `EpisodeOfCare`
10. `CarePlan`
11. `Composition`
12. `MedicationStatement`
13. `QuestionnaireResponse`
### Template per Worker
- Salin pola dari worker yang sudah lengkap (saran: `Medication` untuk transactional, `ServiceRequest` untuk time-based).
- Komponen wajib: tracker, rate-limit handler, KFA/master fetch jika perlu, token refresh, sync log, mapping persistence.
**Output:** Tiap worker = sprint sendiri, release patch (`v1.x.y`).
---
## Phase 5 — Observability & Operasional *(23 minggu, paralel)*
### Langkah Observability
1. **Grafana Dashboard**
- Source: Prometheus `worker_*_total`, `worker_processing_duration_seconds`, `satusehat_response_status_total{code=...}`.
- Panel: throughput per worker, error rate, p95 latency, queue depth (lag dari tracker terhadap MAX(id) source).
2. **Alerting**
- Worker tidak progress > 10 menit.
- Rate-limit hits > 10/min selama 5 menit.
- Token refresh failed > 3 berturut-turut.
3. **Distributed Tracing (opsional)**
- Integrasi OpenTelemetry, trace span dari REST handler → service → repository → API gov't.
4. **Health & Readiness Probe**
- `/health/live`: cek service hidup.
- `/health/ready`: cek DB ping, Redis ping, MinIO ping, last token refresh sukses.
**Output:** Stack monitoring siap pakai (Prometheus + Grafana + Alertmanager).
---
## Phase 6 — UI Dashboard *(repository terpisah, ditangani tim frontend)*
**Tujuan:** Operasional team & admin RS bisa monitor + intervensi tanpa SSH.
### Fitur Inti Dashboard
1. **Sync Monitor**
- Tabel `sync_log` realtime, filter by status, worker, tanggal.
- Re-queue dokumen gagal (button "Retry").
2. **Tracker Cockpit**
- Posisi setiap worker (last_id, last_timestamp) vs. MAX di tabel sumber → lag visual.
- Pause / Resume worker via toggle (butuh control-plane API baru: `PUT /api/v1/worker/{name}/state`).
3. **RBAC Management**
- Hirarki halaman dengan checkbox CRUD level per role (konsumsi `GetRolePermissionTree`).
- Cache invalidation otomatis lewat REST API existing.
4. **KFA Browser**
- Search produk farmasi yang sudah masuk ke DB lokal.
- Trigger ulang puller dari halaman tertentu.
5. **BPJS Console (opsional)**
- Dropdown service VClaim/Antrol → form input → call SDK → tampilkan hasil dekripsi.
---
## Phase 7 — Hardening & Compliance *(jangka panjang)*
- **Audit Trail** lengkap untuk RBAC: siapa, kapan, mengubah apa.
- **Field-Level Encryption** untuk data PII (NIK, alamat) yang tersimpan di sync log.
- **SLA Report** untuk Kemenkes: persentase data terkirim dalam 1×24 jam.
- **Disaster Recovery** runbook: replay dari sync log, re-sync dari ID tertentu.
---
## Ringkasan Timeline Indikatif
| Phase | Durasi | Target Tag | Outcome |
| :--- | :--- | :--- | :--- |
| 0 — Stabilisasi | 12 minggu | `v0.9.0` | Bug kritikal fixed, metrics live |
| 1 — Aktivasi Klinis | 24 minggu | `v1.0.0` | Worker obat & radiologi production |
| 2 — Stateless Tracker | 23 minggu | `v1.1.0` | Multi-replica safe |
| 3 — Event-Driven | 46 minggu | `v1.2.0` | LISTEN/NOTIFY + Kafka |
| 4 — Worker Lengkap | rolling | `v1.x.y` | 13 resource FHIR aktif |
| 5 — Observability | 23 minggu | (paralel) | Grafana + alerting |
| 6 — UI Dashboard | terpisah | (FE repo) | Operator self-service |
| 7 — Hardening | berkelanjutan | — | Compliance & DR |
---
## Quick Wins Bulan Ini
1. **Fix BUG-001** (satusehatClient nil) — 1 jam kerja, dampak besar.
2. **Wire `/metrics`** — 30 menit, langsung kelihatan progress di Prometheus.
3. **Uncomment Worker `Medication`** + soak test 24 jam staging.
4. **Pindahkan password worker ke env** — 1 jam, tutup security finding.
---
*Disusun ulang: Tim Engineering GoPrint, 2026-05-13.*