2021-02-03 05:06:34 +01:00
|
|
|
package memory
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/gob"
|
2021-07-13 04:53:35 +02:00
|
|
|
"sync"
|
2021-07-14 07:53:14 +02:00
|
|
|
"time"
|
2021-02-03 05:06:34 +01:00
|
|
|
|
|
|
|
"github.com/TwinProduction/gatus/core"
|
2021-07-15 04:26:51 +02:00
|
|
|
"github.com/TwinProduction/gatus/storage/store/paging"
|
2021-02-03 05:06:34 +01:00
|
|
|
"github.com/TwinProduction/gatus/util"
|
|
|
|
"github.com/TwinProduction/gocache"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
gob.Register(&core.ServiceStatus{})
|
|
|
|
gob.Register(&core.Uptime{})
|
|
|
|
gob.Register(&core.Result{})
|
|
|
|
gob.Register(&core.Event{})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store that leverages gocache
|
|
|
|
type Store struct {
|
2021-07-13 04:53:35 +02:00
|
|
|
sync.RWMutex
|
2021-02-03 05:06:34 +01:00
|
|
|
file string
|
|
|
|
cache *gocache.Cache
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewStore creates a new store
|
|
|
|
func NewStore(file string) (*Store, error) {
|
|
|
|
store := &Store{
|
|
|
|
file: file,
|
|
|
|
cache: gocache.NewCache().WithMaxSize(gocache.NoMaxSize),
|
|
|
|
}
|
|
|
|
if len(file) > 0 {
|
|
|
|
_, err := store.cache.ReadFromFile(file)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return store, nil
|
|
|
|
}
|
|
|
|
|
2021-07-15 04:26:51 +02:00
|
|
|
// GetAllServiceStatuses returns all monitored core.ServiceStatus
|
2021-02-25 04:41:36 +01:00
|
|
|
// with a subset of core.Result defined by the page and pageSize parameters
|
2021-07-15 04:26:51 +02:00
|
|
|
func (s *Store) GetAllServiceStatuses(params *paging.ServiceStatusParams) map[string]*core.ServiceStatus {
|
2021-02-25 04:41:36 +01:00
|
|
|
serviceStatuses := s.cache.GetAll()
|
|
|
|
pagedServiceStatuses := make(map[string]*core.ServiceStatus, len(serviceStatuses))
|
|
|
|
for k, v := range serviceStatuses {
|
2021-07-15 04:26:51 +02:00
|
|
|
pagedServiceStatuses[k] = ShallowCopyServiceStatus(v.(*core.ServiceStatus), params)
|
2021-02-25 04:41:36 +01:00
|
|
|
}
|
|
|
|
return pagedServiceStatuses
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetServiceStatus returns the service status for a given service name in the given group
|
2021-07-15 04:26:51 +02:00
|
|
|
func (s *Store) GetServiceStatus(groupName, serviceName string, params *paging.ServiceStatusParams) *core.ServiceStatus {
|
|
|
|
return s.GetServiceStatusByKey(util.ConvertGroupAndServiceToKey(groupName, serviceName), params)
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetServiceStatusByKey returns the service status for a given key
|
2021-07-15 04:26:51 +02:00
|
|
|
func (s *Store) GetServiceStatusByKey(key string, params *paging.ServiceStatusParams) *core.ServiceStatus {
|
2021-02-03 05:06:34 +01:00
|
|
|
serviceStatus := s.cache.GetValue(key)
|
|
|
|
if serviceStatus == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-03-05 06:19:21 +01:00
|
|
|
return serviceStatus.(*core.ServiceStatus)
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Insert adds the observed result for the specified service into the store
|
|
|
|
func (s *Store) Insert(service *core.Service, result *core.Result) {
|
2021-07-12 04:22:21 +02:00
|
|
|
key := service.Key()
|
2021-07-13 04:53:35 +02:00
|
|
|
s.Lock()
|
2021-02-03 05:06:34 +01:00
|
|
|
serviceStatus, exists := s.cache.Get(key)
|
|
|
|
if !exists {
|
2021-07-14 07:53:14 +02:00
|
|
|
serviceStatus = core.NewServiceStatus(key, service.Group, service.Name)
|
|
|
|
serviceStatus.(*core.ServiceStatus).Events = append(serviceStatus.(*core.ServiceStatus).Events, &core.Event{
|
|
|
|
Type: core.EventStart,
|
|
|
|
Timestamp: time.Now(),
|
|
|
|
})
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
2021-07-15 04:26:51 +02:00
|
|
|
AddResult(serviceStatus.(*core.ServiceStatus), result)
|
2021-02-03 05:06:34 +01:00
|
|
|
s.cache.Set(key, serviceStatus)
|
2021-07-13 04:53:35 +02:00
|
|
|
s.Unlock()
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteAllServiceStatusesNotInKeys removes all ServiceStatus that are not within the keys provided
|
|
|
|
func (s *Store) DeleteAllServiceStatusesNotInKeys(keys []string) int {
|
|
|
|
var keysToDelete []string
|
|
|
|
for _, existingKey := range s.cache.GetKeysByPattern("*", 0) {
|
|
|
|
shouldDelete := true
|
|
|
|
for _, key := range keys {
|
|
|
|
if existingKey == key {
|
|
|
|
shouldDelete = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if shouldDelete {
|
|
|
|
keysToDelete = append(keysToDelete, existingKey)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s.cache.DeleteAll(keysToDelete)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clear deletes everything from the store
|
|
|
|
func (s *Store) Clear() {
|
|
|
|
s.cache.Clear()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save persists the cache to the store file
|
|
|
|
func (s *Store) Save() error {
|
2021-02-06 02:45:28 +01:00
|
|
|
if len(s.file) > 0 {
|
|
|
|
return s.cache.SaveToFile(s.file)
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
2021-02-06 02:45:28 +01:00
|
|
|
return nil
|
2021-02-03 05:06:34 +01:00
|
|
|
}
|
2021-07-16 04:07:30 +02:00
|
|
|
|
|
|
|
// Close does nothing, because there's nothing to close
|
|
|
|
func (s *Store) Close() {
|
|
|
|
return
|
|
|
|
}
|