first commit
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package servers
|
||||
|
||||
import (
|
||||
"service/internal/infrastructure/cache"
|
||||
"service/internal/infrastructure/config"
|
||||
"service/internal/infrastructure/database"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"service/internal/auth"
|
||||
antrol "service/internal/bpjs/antrol/reference"
|
||||
aplicareBed "service/internal/bpjs/aplicare/bed"
|
||||
apotekDpho "service/internal/bpjs/apotek/reference/dpho"
|
||||
apotekPoli "service/internal/bpjs/apotek/reference/poli"
|
||||
peserta "service/internal/bpjs/vclaim/peserta"
|
||||
sep "service/internal/bpjs/vclaim/sep"
|
||||
roleMaster "service/internal/master/role/master"
|
||||
rolePages "service/internal/master/role/pages"
|
||||
rolePermission "service/internal/master/role/permission"
|
||||
satuSehatAuth "service/internal/satusehat/reference/auth"
|
||||
satuSehatKfa "service/internal/satusehat/reference/kfa"
|
||||
satuSehatLocation "service/internal/satusehat/reference/location"
|
||||
satuSehatOrganization "service/internal/satusehat/reference/organization"
|
||||
satuSehatPatient "service/internal/satusehat/reference/patient"
|
||||
satuSehatPractitioner "service/internal/satusehat/reference/practitioner"
|
||||
"service/internal/satusehat/usecase/allergyintolerance"
|
||||
"service/internal/satusehat/usecase/careplan"
|
||||
clinicalimpression "service/internal/satusehat/usecase/clinicalImpression"
|
||||
"service/internal/satusehat/usecase/composition"
|
||||
"service/internal/satusehat/usecase/condition"
|
||||
"service/internal/satusehat/usecase/diagnosticreport"
|
||||
"service/internal/satusehat/usecase/encounter"
|
||||
"service/internal/satusehat/usecase/episodeofcare"
|
||||
"service/internal/satusehat/usecase/imagingstudy"
|
||||
"service/internal/satusehat/usecase/immunization"
|
||||
"service/internal/satusehat/usecase/medication"
|
||||
"service/internal/satusehat/usecase/medicationdispense"
|
||||
"service/internal/satusehat/usecase/medicationrequest"
|
||||
"service/internal/satusehat/usecase/medicationstatement"
|
||||
"service/internal/satusehat/usecase/observation"
|
||||
"service/internal/satusehat/usecase/procedure"
|
||||
"service/internal/satusehat/usecase/questionnaireresponse"
|
||||
"service/internal/satusehat/usecase/servicerequest"
|
||||
"service/internal/satusehat/usecase/specimen"
|
||||
)
|
||||
|
||||
// MasterServices menampung kumpulan service untuk domain Master Data
|
||||
type MasterServices struct {
|
||||
RolePages rolePages.Service
|
||||
RolePermission rolePermission.Service
|
||||
RoleMaster roleMaster.Service
|
||||
}
|
||||
|
||||
// VClaimServices menampung kumpulan service untuk integrasi BPJS VClaim
|
||||
type VClaimServices struct {
|
||||
Sep sep.Service
|
||||
Peserta peserta.Service
|
||||
}
|
||||
|
||||
// AntrolServices menampung kumpulan service untuk integrasi BPJS Antrean RS
|
||||
type AntrolServices struct {
|
||||
Reference antrol.Service
|
||||
}
|
||||
|
||||
// AplicaresServices menampung kumpulan service untuk integrasi BPJS Aplicares
|
||||
type AplicaresServices struct {
|
||||
Bed aplicareBed.Service
|
||||
}
|
||||
|
||||
// ApotekServices menampung kumpulan service untuk integrasi BPJS Apotek
|
||||
type ApotekServices struct {
|
||||
DPHO apotekDpho.Service
|
||||
Poli apotekPoli.Service
|
||||
}
|
||||
|
||||
// SatuSehatServices menampung kumpulan service untuk integrasi Kemenkes Satu Sehat
|
||||
type SatuSehatServices struct {
|
||||
Auth satuSehatAuth.Service
|
||||
Patient satuSehatPatient.Service
|
||||
Practitioner satuSehatPractitioner.Service
|
||||
Organization satuSehatOrganization.Service
|
||||
Location satuSehatLocation.Service
|
||||
KFA satuSehatKfa.Service
|
||||
|
||||
// Usecase Services
|
||||
AllergyIntolerance allergyintolerance.Service
|
||||
CarePlan careplan.Service
|
||||
ClinicalImpression clinicalimpression.Service
|
||||
Composition composition.Service
|
||||
Condition condition.Service
|
||||
DiagnosticReport diagnosticreport.Service
|
||||
Encounter encounter.Service
|
||||
EpisodeOfCare episodeofcare.Service
|
||||
ImagingStudy imagingstudy.Service
|
||||
Immunization immunization.Service
|
||||
Medication medication.Service
|
||||
MedicationDispense medicationdispense.Service
|
||||
MedicationRequest medicationrequest.Service
|
||||
MedicationStatement medicationstatement.Service
|
||||
Observation observation.Service
|
||||
Procedure procedure.Service
|
||||
QuestionnaireResponse questionnaireresponse.Service
|
||||
ServiceRequest servicerequest.Service
|
||||
Specimen specimen.Service
|
||||
}
|
||||
|
||||
// ServiceRegistry berfungsi sebagai Dependency Injection Container untuk transport HTTP.
|
||||
// Struktur ini mencegah membengkaknya parameter pada saat inisialisasi API.
|
||||
type ServiceRegistry struct {
|
||||
Config *config.Config
|
||||
DBManager database.Service
|
||||
PrimaryDB *gorm.DB
|
||||
CacheManager *cache.Manager
|
||||
|
||||
// Modul Aplikasi (Pisahkan berdasarkan Bounded Context)
|
||||
AuthService auth.Service
|
||||
Master *MasterServices
|
||||
VClaim *VClaimServices
|
||||
Antrol *AntrolServices
|
||||
Aplicare *AplicaresServices
|
||||
Apotek *ApotekServices
|
||||
SatuSehat *SatuSehatServices
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
// internal/infrastructure/transport/http/servers/server.go
|
||||
package servers
|
||||
|
||||
import (
|
||||
"context" // PERBAIKAN: Tambahkan import untuk graceful shutdown
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"service/internal/infrastructure/cache" // PERBAIKAN: Tambahkan import cache
|
||||
"service/internal/infrastructure/config"
|
||||
"service/internal/infrastructure/transport/http/middleware"
|
||||
"service/internal/infrastructure/transport/http/routes"
|
||||
|
||||
antrolHttp "service/internal/infrastructure/transport/http/handlers/bpjs/antrol"
|
||||
aplicareHttp "service/internal/infrastructure/transport/http/handlers/bpjs/aplicare"
|
||||
apotekHttp "service/internal/infrastructure/transport/http/handlers/bpjs/apotek"
|
||||
vclaimHttp "service/internal/infrastructure/transport/http/handlers/bpjs/vclaim"
|
||||
authHttp "service/internal/infrastructure/transport/http/handlers/main/auth"
|
||||
healthHttp "service/internal/infrastructure/transport/http/handlers/main/health"
|
||||
roleHttp "service/internal/infrastructure/transport/http/handlers/main/master/roles"
|
||||
satuSehatRefHttp "service/internal/infrastructure/transport/http/handlers/satusehat/reference"
|
||||
satuSehatUsecaseHttp "service/internal/infrastructure/transport/http/handlers/satusehat/usecase"
|
||||
|
||||
// Inisialisasi pkg
|
||||
"service/pkg/errors"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
swaggerFiles "github.com/swaggo/files"
|
||||
ginSwagger "github.com/swaggo/gin-swagger"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
engine *gin.Engine
|
||||
config *config.ServerRESTConfig
|
||||
cacheConfig cache.CacheConfig // PERBAIKAN: Tambahkan cacheConfig
|
||||
httpServer *http.Server // PERBAIKAN: Simpan instance http.Server untuk graceful shutdown
|
||||
}
|
||||
|
||||
// NewHTTPServer membuat instance server HTTP baru
|
||||
func NewHTTPServer(
|
||||
restConfig *config.ServerRESTConfig,
|
||||
registry *ServiceRegistry,
|
||||
) *Server {
|
||||
if !restConfig.Enabled {
|
||||
log.Println("HTTP server is disabled in configuration.")
|
||||
return &Server{
|
||||
config: restConfig,
|
||||
}
|
||||
}
|
||||
|
||||
// Set mode Gin berdasarkan konfigurasi global
|
||||
if registry.Config.Server.Mode == "release" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
engine := gin.New()
|
||||
|
||||
// Middleware untuk recovery dan penanganan error konsisten.
|
||||
// Diletakkan paling awal untuk menangkap panic dari middleware/handler lain.
|
||||
engine.Use(errors.CombinedMiddleware())
|
||||
|
||||
// Middleware lainnya
|
||||
engine.Use(middleware.LoggingMiddleware())
|
||||
engine.Use(middleware.SecurityMiddleware())
|
||||
engine.Use(middleware.CORSMiddleware())
|
||||
// PERBAIKAN: Berikan cacheManager ke RateLimitMiddleware
|
||||
engine.Use(middleware.RateLimitMiddleware(registry.CacheManager))
|
||||
|
||||
// Inisialisasi ModuleHandlers secara dinamis berdasarkan fitur yang aktif
|
||||
appHandlers := &routes.ModuleHandlers{}
|
||||
|
||||
if registry.AuthService != nil {
|
||||
appHandlers.Auth = authHttp.NewAuthHandler(registry.AuthService)
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Master
|
||||
if registry.Master != nil {
|
||||
if registry.Master.RolePages != nil {
|
||||
appHandlers.RolePages = roleHttp.NewRolPagesHandler(registry.Master.RolePages)
|
||||
}
|
||||
if registry.Master.RolePermission != nil {
|
||||
appHandlers.RolePermission = roleHttp.NewRolPermissionHandler(registry.Master.RolePermission)
|
||||
}
|
||||
if registry.Master.RoleMaster != nil {
|
||||
appHandlers.RoleMaster = roleHttp.NewRoleMasterHandler(registry.Master.RoleMaster)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul VClaim
|
||||
if registry.VClaim != nil {
|
||||
if registry.VClaim.Sep != nil {
|
||||
appHandlers.Sep = vclaimHttp.NewSepHandler(registry.VClaim.Sep)
|
||||
}
|
||||
if registry.VClaim.Peserta != nil {
|
||||
appHandlers.Peserta = vclaimHttp.NewPesertaHandler(registry.VClaim.Peserta)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Antrol
|
||||
if registry.Antrol != nil {
|
||||
if registry.Antrol.Reference != nil {
|
||||
appHandlers.Antrol = antrolHttp.NewAntrolHandler(registry.Antrol.Reference)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Aplicares
|
||||
if registry.Aplicare != nil {
|
||||
if registry.Aplicare.Bed != nil {
|
||||
appHandlers.AplicareBed = aplicareHttp.NewBedHandler(registry.Aplicare.Bed)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Apotek
|
||||
if registry.Apotek != nil {
|
||||
if registry.Apotek.DPHO != nil && registry.Apotek.Poli != nil {
|
||||
appHandlers.ApotekReference = apotekHttp.NewReferenceHandler(registry.Apotek.DPHO, registry.Apotek.Poli)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Satu Sehat
|
||||
if registry.SatuSehat != nil {
|
||||
if registry.SatuSehat.Auth != nil {
|
||||
appHandlers.SatuSehatAuth = satuSehatRefHttp.NewAuthHandler(registry.SatuSehat.Auth)
|
||||
}
|
||||
if registry.SatuSehat.Patient != nil {
|
||||
appHandlers.SatuSehatPatient = satuSehatRefHttp.NewPatientHandler(registry.SatuSehat.Patient)
|
||||
}
|
||||
if registry.SatuSehat.Practitioner != nil {
|
||||
appHandlers.SatuSehatPractitioner = satuSehatRefHttp.NewPractitionerHandler(registry.SatuSehat.Practitioner)
|
||||
}
|
||||
if registry.SatuSehat.Organization != nil {
|
||||
appHandlers.SatuSehatOrganization = satuSehatRefHttp.NewOrganizationHandler(registry.SatuSehat.Organization)
|
||||
}
|
||||
if registry.SatuSehat.Location != nil {
|
||||
appHandlers.SatuSehatLocation = satuSehatRefHttp.NewLocationHandler(registry.SatuSehat.Location)
|
||||
}
|
||||
if registry.SatuSehat.KFA != nil {
|
||||
appHandlers.SatuSehatKFA = satuSehatRefHttp.NewKFAHandler(registry.SatuSehat.KFA)
|
||||
}
|
||||
|
||||
// Inisialisasi Handlers Modul Satu Sehat Usecase
|
||||
if registry.SatuSehat.AllergyIntolerance != nil {
|
||||
appHandlers.SSAllergyIntolerance = satuSehatUsecaseHttp.NewAllergyIntoleranceHandler(registry.SatuSehat.AllergyIntolerance)
|
||||
}
|
||||
if registry.SatuSehat.CarePlan != nil {
|
||||
appHandlers.SSCarePlan = satuSehatUsecaseHttp.NewCarePlanHandler(registry.SatuSehat.CarePlan)
|
||||
}
|
||||
if registry.SatuSehat.ClinicalImpression != nil {
|
||||
appHandlers.SSClinicalImpression = satuSehatUsecaseHttp.NewClinicalImpressionHandler(registry.SatuSehat.ClinicalImpression)
|
||||
}
|
||||
if registry.SatuSehat.Composition != nil {
|
||||
appHandlers.SSComposition = satuSehatUsecaseHttp.NewCompositionHandler(registry.SatuSehat.Composition)
|
||||
}
|
||||
if registry.SatuSehat.Condition != nil {
|
||||
appHandlers.SSCondition = satuSehatUsecaseHttp.NewConditionHandler(registry.SatuSehat.Condition)
|
||||
}
|
||||
if registry.SatuSehat.DiagnosticReport != nil {
|
||||
appHandlers.SSDiagnosticReport = satuSehatUsecaseHttp.NewDiagnosticReportHandler(registry.SatuSehat.DiagnosticReport)
|
||||
}
|
||||
if registry.SatuSehat.Encounter != nil {
|
||||
appHandlers.SSEncounter = satuSehatUsecaseHttp.NewEncounterHandler(registry.SatuSehat.Encounter)
|
||||
}
|
||||
if registry.SatuSehat.EpisodeOfCare != nil {
|
||||
appHandlers.SSEpisodeOfCare = satuSehatUsecaseHttp.NewEpisodeOfCareHandler(registry.SatuSehat.EpisodeOfCare)
|
||||
}
|
||||
if registry.SatuSehat.ImagingStudy != nil {
|
||||
appHandlers.SSImagingStudy = satuSehatUsecaseHttp.NewImagingStudyHandler(registry.SatuSehat.ImagingStudy)
|
||||
}
|
||||
if registry.SatuSehat.Immunization != nil {
|
||||
appHandlers.SSImmunization = satuSehatUsecaseHttp.NewImmunizationHandler(registry.SatuSehat.Immunization)
|
||||
}
|
||||
if registry.SatuSehat.Medication != nil {
|
||||
appHandlers.SSMedication = satuSehatUsecaseHttp.NewMedicationHandler(registry.SatuSehat.Medication)
|
||||
}
|
||||
if registry.SatuSehat.MedicationDispense != nil {
|
||||
appHandlers.SSMedicationDispense = satuSehatUsecaseHttp.NewMedicationDispenseHandler(registry.SatuSehat.MedicationDispense)
|
||||
}
|
||||
if registry.SatuSehat.MedicationRequest != nil {
|
||||
appHandlers.SSMedicationRequest = satuSehatUsecaseHttp.NewMedicationRequestHandler(registry.SatuSehat.MedicationRequest)
|
||||
}
|
||||
if registry.SatuSehat.MedicationStatement != nil {
|
||||
appHandlers.SSMedicationStatement = satuSehatUsecaseHttp.NewMedicationStatementHandler(registry.SatuSehat.MedicationStatement)
|
||||
}
|
||||
if registry.SatuSehat.Observation != nil {
|
||||
appHandlers.SSObservation = satuSehatUsecaseHttp.NewObservationHandler(registry.SatuSehat.Observation)
|
||||
}
|
||||
if registry.SatuSehat.Procedure != nil {
|
||||
appHandlers.SSProcedure = satuSehatUsecaseHttp.NewProcedureHandler(registry.SatuSehat.Procedure)
|
||||
}
|
||||
if registry.SatuSehat.QuestionnaireResponse != nil {
|
||||
appHandlers.SSQuestionnaireResponse = satuSehatUsecaseHttp.NewQuestionnaireResponseHandler(registry.SatuSehat.QuestionnaireResponse)
|
||||
}
|
||||
if registry.SatuSehat.ServiceRequest != nil {
|
||||
appHandlers.SSServiceRequest = satuSehatUsecaseHttp.NewServiceRequestHandler(registry.SatuSehat.ServiceRequest)
|
||||
}
|
||||
if registry.SatuSehat.Specimen != nil {
|
||||
appHandlers.SSSpecimen = satuSehatUsecaseHttp.NewSpecimenHandler(registry.SatuSehat.Specimen)
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi Health Handler dengan dependensi yang benar
|
||||
// Gunakan constructor baru yang menerima cache manager
|
||||
healthHandler := healthHttp.NewHealthHandlerWithCache(registry.PrimaryDB, registry.CacheManager, registry.Config, registry.DBManager)
|
||||
|
||||
// Setup routes menggunakan handler yang sudah diinisialisasi
|
||||
routes.SetupRoutes(
|
||||
engine,
|
||||
registry.Config,
|
||||
registry.CacheManager,
|
||||
healthHandler,
|
||||
appHandlers,
|
||||
)
|
||||
|
||||
return &Server{
|
||||
engine: engine,
|
||||
config: restConfig,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterSwagger mendaftarkan dokumentasi Swagger UI
|
||||
func (s *Server) RegisterSwagger() {
|
||||
if s.engine == nil {
|
||||
log.Println("Cannot register Swagger: engine is nil (server disabled)")
|
||||
return
|
||||
}
|
||||
s.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
}
|
||||
|
||||
// Start menjalankan server HTTP
|
||||
func (s *Server) Start(globalConfig *config.ServerConfig) error {
|
||||
if !s.config.Enabled {
|
||||
log.Println("HTTP server is disabled, not starting.")
|
||||
return nil
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf(":%d", s.config.Port)
|
||||
log.Printf("Starting HTTP server on %s", addr)
|
||||
|
||||
// PERBAIKAN: Simpan instance server ke struct
|
||||
s.httpServer = &http.Server{
|
||||
Addr: addr,
|
||||
Handler: s.engine,
|
||||
ReadTimeout: time.Duration(globalConfig.ReadTimeout) * time.Second,
|
||||
WriteTimeout: time.Duration(globalConfig.WriteTimeout) * time.Second,
|
||||
IdleTimeout: 60 * time.Second, // Good practice to have an idle timeout
|
||||
}
|
||||
|
||||
return s.httpServer.ListenAndServe()
|
||||
}
|
||||
|
||||
// PERBAIKAN: Tambahkan method untuk graceful shutdown
|
||||
// Shutdown memberhentikan server HTTP dengan graceful shutdown
|
||||
func (s *Server) Shutdown(ctx context.Context) error {
|
||||
if s.httpServer == nil {
|
||||
return nil
|
||||
}
|
||||
log.Println("Shutting down HTTP server...")
|
||||
return s.httpServer.Shutdown(ctx)
|
||||
}
|
||||
|
||||
// GetEngine mengembalikan instance Gin engine (terutama untuk testing)
|
||||
func (s *Server) GetEngine() *gin.Engine {
|
||||
return s.engine
|
||||
}
|
||||
Reference in New Issue
Block a user