package immunization import ( "context" "encoding/json" "fmt" "log" "net/http" "os" "strconv" "strings" "time" "service/internal/infrastructure/database" extapi "service/internal/worker/interface" ) const trackerFile = "last_migrated_immunization_id.txt" 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("[IMMUNIZATION WORKER] Memulai proses sinkronisasi...") lastID := w.readLastID() for { select { case <-ctx.Done(): log.Println("[IMMUNIZATION WORKER] Proses dihentikan.") return default: } im, err := w.repo.GetNextImmunization(ctx, lastID) if err != nil { time.Sleep(5 * time.Second) continue } internalPayload := MapToInternalAPI(im, w.cfg.OrganizationID) reqURL := fmt.Sprintf("%s/satusehat/immunization", strings.TrimRight(w.cfg.InternalBaseURL, "/")) 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) } } } _ = w.repo.SaveSyncLog(ctx, MapToSyncLog(im.IdxImunisasi, fhirID, internalPayload, respBody, status, errMsg)) if status == "SUCCESS" && fhirID != "" { _ = w.repo.SaveSatuSehatID(ctx, im.IdxImunisasi, fhirID) } lastID = im.IdxImunisasi os.WriteFile(trackerFile, []byte(strconv.FormatInt(lastID, 10)), 0644) time.Sleep(500 * time.Millisecond) } } func (w *worker) readLastID() int64 { data, _ := os.ReadFile(trackerFile) id, _ := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) return id }