package imagingstudy import ( "context" "database/sql" "encoding/json" "fmt" "log" "net/http" "strings" "time" "service/internal/infrastructure/database" extapi "service/internal/worker/interface" ) type Config struct { DBManager database.Service InternalBaseURL string InternalToken string OrganizationID string } type WorkerService interface { Run(ctx context.Context) } type worker struct { cfg Config repo Repository apiClient extapi.Client } func NewWorker(cfg Config) WorkerService { return &worker{cfg: cfg, repo: NewRepository(cfg.DBManager), apiClient: extapi.NewClient(15 * time.Second)} } func (w *worker) Run(ctx context.Context) { log.Println("[IMAGINGSTUDY WORKER] Memulai proses sinkronisasi...") for { select { case <-ctx.Done(): log.Println("[IMAGINGSTUDY WORKER] Proses dihentikan.") return default: } // 1. Ambil data dengan status belum terkirim (IS NULL atau FAILED) isData, err := w.repo.GetNextPendingRequest(ctx) if err != nil { if err == sql.ErrNoRows { // Jika tidak ada data antrean, istirahat lebih lama time.Sleep(10 * time.Second) continue } log.Printf("[IMAGINGSTUDY WORKER] Error query db: %v", err) time.Sleep(5 * time.Second) continue } // 2. Petakan ke payload SATUSEHAT via Internal API internalPayload := MapToInternalAPI(isData, w.cfg.OrganizationID) reqURL := fmt.Sprintf("%s/satusehat/imagingstudy", strings.TrimRight(w.cfg.InternalBaseURL, "/")) // 3. Eksekusi pengiriman API respBody, statusCode, err := w.apiClient.PostJSON(ctx, reqURL, w.cfg.InternalToken, internalPayload) var status, errMsg, fhirID string if err != nil || (statusCode != http.StatusOK && statusCode != http.StatusCreated) { status, errMsg = "FAILED", fmt.Sprintf("Err: %v, HTTP: %d", err, statusCode) } else { status = "SUCCESS" var res map[string]interface{} if json.Unmarshal(respBody, &res) == nil { if data, ok := res["data"].(map[string]interface{}); ok { fhirID, _ = data["id"].(string) } else { fhirID, _ = res["id"].(string) } } } // Buat response data berupa string JSON untuk log & penyimpanan error logData := MapToSyncLog(isData.RequestID, fhirID, internalPayload, respBody, status, errMsg) logBytes, _ := json.Marshal(logData) // 4. Update status ke tabel data_service_requests errUpdate := w.repo.UpdateSyncStatus(ctx, isData.RequestID, status, string(logBytes)) if errUpdate != nil { log.Printf("[IMAGINGSTUDY WORKER] Gagal update status di database untuk ID %s: %v", isData.RequestID, errUpdate) } else { log.Printf("[IMAGINGSTUDY WORKER] Sukses proses ID %s dengan status %s", isData.RequestID, status) } time.Sleep(500 * time.Millisecond) } }