From a4050c28dc9cfb2edcc3716b91af4a8ba146637b Mon Sep 17 00:00:00 2001 From: ostiwe Date: Wed, 20 Aug 2025 15:25:20 +0300 Subject: [PATCH] feat: Added ID field to PublicService DTO, update fields in Service model, fix CalculateUptimePercent method, transform services to Public services in goroutines --- dto/service.go | 3 ++- model/service.go | 8 ++++---- model/status.go | 11 +++++----- transform/service.go | 48 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/dto/service.go b/dto/service.go index 9c38847..c627d12 100644 --- a/dto/service.go +++ b/dto/service.go @@ -3,8 +3,9 @@ package dto import "git.ostiwe.com/ostiwe-com/status/model" type PublicService struct { + ID int `json:"id"` Name string `json:"name"` - Description string `json:"description"` + Description *string `json:"description"` Statuses []model.Status `json:"statuses"` Uptime float64 `json:"uptime"` } diff --git a/model/service.go b/model/service.go index a6c9afa..5d29d2f 100644 --- a/model/service.go +++ b/model/service.go @@ -18,9 +18,9 @@ type Service struct { // Human-readable service name Name string `gorm:"size:255;not null" json:"name"` // Human-readable service description - Description string `gorm:"size:255" json:"description"` - PublicDescription string `gorm:"size:255" json:"public_description"` - Public *bool `gorm:"default:false" json:"public"` + Description *string `gorm:"size:255" json:"description"` + PublicDescription *string `gorm:"size:255" json:"public_description"` + Public *bool `gorm:"default:false" json:"public"` // Host to check, for example 192.168.1.44 Host string `gorm:"size:255;not null" json:"host"` // Type for check, for now is TCP or HTTP @@ -67,7 +67,7 @@ func (s Service) CalculateUptimePercent() float64 { return uptime } - sla := 100 - (float64(len(s.Statuses)) / float64(countOfOkStatus)) + sla := 100 / (float64(len(s.Statuses)) / float64(countOfOkStatus)) ratio := math.Pow(10, float64(2)) uptime = math.Round(sla*ratio) / ratio diff --git a/model/status.go b/model/status.go index 286c623..1d3aa46 100644 --- a/model/status.go +++ b/model/status.go @@ -9,17 +9,18 @@ import ( type StatusCode string const ( - StatusOK StatusCode = "ok" // Means - response ok, service is alive - StatusFailed StatusCode = "failed" // Means - response failed, all tries failed, service down - StatusWarn StatusCode = "warn" // Means - response failed after N tries and still watched + StatusOK StatusCode = "ok" // Means - response ok, service is alive + StatusFailed StatusCode = "failed" // Means - response failed, all tries failed, service down + StatusWarn StatusCode = "warn" // Means - response failed after N tries and still watched + StatusUncheck StatusCode = "unchecked" // Means - no data ) type Status struct { - ID int `gorm:"primary_key;auto_increment" json:"-"` + ID int `gorm:"primary_key;auto_increment" json:"id"` ServiceID int `gorm:"one" json:"-"` Status StatusCode `gorm:"size:255;not null" json:"status"` Description *string `gorm:"size:255" json:"description"` - CreatedAt time.Time `json:"created_at"` + CreatedAt time.Time `json:"createdAt"` } func (Status) TableName() string { diff --git a/transform/service.go b/transform/service.go index 22100f0..29ba5d9 100644 --- a/transform/service.go +++ b/transform/service.go @@ -1,25 +1,67 @@ package transform import ( + "slices" + "sync" + "git.ostiwe.com/ostiwe-com/status/dto" "git.ostiwe.com/ostiwe-com/status/model" ) +const maxStatuses = 60 + func PublicServices(items ...model.Service) []dto.PublicService { result := make([]dto.PublicService, 0, len(items)) + mu := new(sync.Mutex) + + chunked := slices.Chunk(items, 40) + + for services := range chunked { + wg := new(sync.WaitGroup) + wg.Add(len(services)) + + for i := range services { + go func(_wg *sync.WaitGroup, item model.Service) { + defer _wg.Done() + + transformed := PublicService(item) + mu.Lock() + result = append(result, transformed) + mu.Unlock() + }(wg, services[i]) + } + + wg.Wait() - for _, item := range items { - result = append(result, PublicService(item)) } return result } func PublicService(item model.Service) dto.PublicService { + statuses := make([]model.Status, maxStatuses) + itemStatusLen := len(item.Statuses) + + for i := range statuses { + if i > itemStatusLen-1 { + break + } + statuses[i] = item.Statuses[i] + } + + for i := range statuses { + if statuses[i].Status == "" { + statuses[i].Status = model.StatusUncheck + } + } + + slices.Reverse(statuses) + return dto.PublicService{ + ID: item.ID, Name: item.Name, Description: item.PublicDescription, - Statuses: item.Statuses, + Statuses: statuses, Uptime: item.CalculateUptimePercent(), } }