Medication Update
This commit is contained in:
+201
-200
@@ -10,25 +10,7 @@ import (
|
||||
"service/internal/infrastructure/config"
|
||||
"service/internal/infrastructure/database"
|
||||
"service/internal/interfaces/satusehat"
|
||||
"service/internal/worker/satusehat/allergyintolerance"
|
||||
"service/internal/worker/satusehat/careplan"
|
||||
"service/internal/worker/satusehat/clinicalimpression"
|
||||
"service/internal/worker/satusehat/composition"
|
||||
"service/internal/worker/satusehat/condition"
|
||||
"service/internal/worker/satusehat/diagnosticreport"
|
||||
"service/internal/worker/satusehat/encounter"
|
||||
"service/internal/worker/satusehat/episodeofcare"
|
||||
"service/internal/worker/satusehat/imagingstudy"
|
||||
"service/internal/worker/satusehat/immunization"
|
||||
"service/internal/worker/satusehat/medication"
|
||||
"service/internal/worker/satusehat/medicationdispense"
|
||||
"service/internal/worker/satusehat/medicationrequest"
|
||||
"service/internal/worker/satusehat/medicationstatement"
|
||||
"service/internal/worker/satusehat/observation"
|
||||
"service/internal/worker/satusehat/procedure"
|
||||
"service/internal/worker/satusehat/questionnaireresponse"
|
||||
"service/internal/worker/satusehat/servicerequest"
|
||||
"service/internal/worker/satusehat/specimen"
|
||||
"service/pkg/logger"
|
||||
)
|
||||
|
||||
@@ -37,6 +19,11 @@ type Manager struct {
|
||||
cfg *config.Config
|
||||
db database.Service
|
||||
satusehatClient satusehat.SatuSehatClient
|
||||
|
||||
// Auth state for all workers
|
||||
accessToken string
|
||||
refreshToken string
|
||||
tokenMutex sync.RWMutex
|
||||
}
|
||||
|
||||
// NewManager membuat instance Manager baru
|
||||
@@ -52,20 +39,21 @@ func NewManager(cfg *config.Config, db database.Service, satusehatClient satuseh
|
||||
func (m *Manager) Start(ctx context.Context) {
|
||||
logger.Default().Info("Starting background workers...")
|
||||
|
||||
// Lakukan login awal untuk mendapatkan token bagi semua worker
|
||||
if err := m.login(ctx); err != nil {
|
||||
logger.Default().Fatal("Initial login for workers failed, stopping.", logger.ErrorField(err))
|
||||
return
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Tentukan Organization ID (Bisa dari Environment Variable atau Config Struct)
|
||||
orgID := os.Getenv("SATUSEHAT_ORGANIZATION_ID")
|
||||
orgID := os.Getenv("SATUSEHAT_ORG_ID")
|
||||
if orgID == "" {
|
||||
logger.Default().Warn("SATUSEHAT_ORGANIZATION_ID is not set in environment variables")
|
||||
logger.Default().Warn("SATUSEHAT_ORG_ID is not set in environment variables")
|
||||
}
|
||||
|
||||
internalPort := 8080
|
||||
if m.cfg != nil && m.cfg.Server.REST.Port != 0 {
|
||||
internalPort = m.cfg.Server.REST.Port
|
||||
}
|
||||
internalBaseURL := fmt.Sprintf("http://localhost:%d/api/v1", internalPort)
|
||||
internalToken := os.Getenv("INTERNAL_API_TOKEN")
|
||||
internalBaseURL := m.cfg.SatuSehat.InternalFHIRServerURL
|
||||
|
||||
// Jobs mendefinisikan urutan dan jeda waktu (delay) boot-up setiap worker.
|
||||
// Konfigurasi waktu ini mencegah perebutan resource di awal (thundering herd)
|
||||
@@ -76,195 +64,208 @@ func (m *Manager) Start(ctx context.Context) {
|
||||
delay time.Duration
|
||||
run func(context.Context)
|
||||
}{
|
||||
// {
|
||||
// name: "Encounter",
|
||||
// delay: 5 * time.Second, // Memberikan jeda 5 detik agar Encounter mendapat porsi jalan lebih dulu
|
||||
// run: func(c context.Context) {
|
||||
// encounter.NewWorker(encounter.Config{
|
||||
// DBManager: m.db, InternalBaseURL: internalBaseURL, OrganizationID: orgID,
|
||||
// }).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "Condition",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // condition.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
{
|
||||
name: "Medication (Master)",
|
||||
delay: 0, // Master data berjalan seketika
|
||||
run: func(c context.Context) {
|
||||
medication.NewWorker(medication.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Encounter",
|
||||
delay: 5 * time.Second, // Memberikan jeda 5 detik agar Encounter mendapat porsi jalan lebih dulu
|
||||
run: func(c context.Context) {
|
||||
encounter.NewWorker(encounter.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Condition",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
condition.NewWorker(condition.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Observation",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
observation.NewWorker(observation.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Procedure",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
procedure.NewWorker(procedure.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "AllergyIntolerance",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
allergyintolerance.NewWorker(allergyintolerance.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ClinicalImpression",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
clinicalimpression.NewWorker(clinicalimpression.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Immunization",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
immunization.NewWorker(immunization.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ServiceRequest",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
servicerequest.NewWorker(servicerequest.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Specimen",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
specimen.NewWorker(specimen.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "DiagnosticReport",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
diagnosticreport.NewWorker(diagnosticreport.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ImagingStudy",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
imagingstudy.NewWorker(imagingstudy.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Composition",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
composition.NewWorker(composition.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CarePlan",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
careplan.NewWorker(careplan.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "EpisodeOfCare",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
episodeofcare.NewWorker(episodeofcare.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MedicationRequest",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
medicationrequest.NewWorker(medicationrequest.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MedicationDispense",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
medicationdispense.NewWorker(medicationdispense.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MedicationStatement",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
medicationstatement.NewWorker(medicationstatement.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "QuestionnaireResponse",
|
||||
delay: 2 * time.Second,
|
||||
run: func(c context.Context) {
|
||||
questionnaireresponse.NewWorker(questionnaireresponse.Config{
|
||||
DBManager: m.db, InternalBaseURL: internalBaseURL, InternalToken: internalToken, OrganizationID: orgID,
|
||||
}).Run(c)
|
||||
DBManager: m.db,
|
||||
InternalBaseURL: internalBaseURL,
|
||||
OrganizationID: orgID,
|
||||
}, m).Run(c)
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: "Observation",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // observation.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "Procedure",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // procedure.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "AllergyIntolerance",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // allergyintolerance.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "ClinicalImpression",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // clinicalimpression.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "Immunization",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // immunization.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "ServiceRequest (Default)",
|
||||
// delay: 0,
|
||||
// run: func(c context.Context) {
|
||||
// servicerequest.NewDefaultWorker(servicerequest.Config{
|
||||
// DBManager: m.db,
|
||||
// InternalBaseURL: internalBaseURL,
|
||||
// OrganizationID: orgID,
|
||||
// }, m).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "ServiceRequest (Radiology)",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// servicerequest.NewRadiologyWorker(servicerequest.Config{
|
||||
// DBManager: m.db,
|
||||
// InternalBaseURL: internalBaseURL,
|
||||
// OrganizationID: orgID,
|
||||
// }, m).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "Specimen",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // specimen.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "DiagnosticReport",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // diagnosticreport.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "ImagingStudy",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // The Manager 'm' now acts as the TokenManager
|
||||
// imagingstudy.NewWorker(imagingstudy.Config{
|
||||
// DBManager: m.db, InternalBaseURL: internalBaseURL, OrganizationID: orgID,
|
||||
// }, m).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "Composition",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // composition.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "CarePlan",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // careplan.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "EpisodeOfCare",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // episodeofcare.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "MedicationRequest",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // medicationrequest.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "MedicationDispense",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // medicationdispense.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "MedicationStatement",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // medicationstatement.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: "QuestionnaireResponse",
|
||||
// delay: 2 * time.Second,
|
||||
// run: func(c context.Context) {
|
||||
// // TODO: Refactor this worker
|
||||
// // questionnaireresponse.NewWorker(...).Run(c)
|
||||
// },
|
||||
// },
|
||||
}
|
||||
|
||||
// Eksekusi semua background worker secara tertib
|
||||
// Eksekusi semua background worker secara tertib dengan delay bertingkat
|
||||
go func() {
|
||||
for _, job := range jobs {
|
||||
// Jeda startup, dapat di-interrupt oleh Context Cancel (Shutdown System)
|
||||
if job.delay > 0 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-time.After(job.delay):
|
||||
}
|
||||
baseDelay := 10 * time.Second // Jeda 10 detik antar tiap worker untuk cegah spike di awal
|
||||
|
||||
for i, job := range jobs {
|
||||
// Hitung delay bertingkat: (index) * baseDelay
|
||||
staggeredDelay := time.Duration(i) * baseDelay
|
||||
|
||||
// Jika job memiliki delay statis yang lebih besar, utamakan nilai tersebut
|
||||
if job.delay > staggeredDelay {
|
||||
staggeredDelay = job.delay
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
j := job // copy pointer untuk goroutine loop
|
||||
j := job
|
||||
d := staggeredDelay
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if d > 0 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-time.After(d):
|
||||
}
|
||||
}
|
||||
|
||||
logger.Default().Info(fmt.Sprintf("[%s WORKER] Started", j.name))
|
||||
j.run(ctx)
|
||||
logger.Default().Info(fmt.Sprintf("[%s WORKER] Stopped", j.name))
|
||||
|
||||
Reference in New Issue
Block a user