@@ -211,6 +211,23 @@ func (s *Store) DeleteAllTriggeredAlertsNotInChecksumsByEndpoint(ep *endpoint.En
|
||||
return 0
|
||||
}
|
||||
|
||||
// HasEndpointStatusNewerThan checks whether an endpoint has a status newer than the provided timestamp
|
||||
func (s *Store) HasEndpointStatusNewerThan(key string, timestamp time.Time) (bool, error) {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
endpointStatus := s.cache.GetValue(key)
|
||||
if endpointStatus == nil {
|
||||
// If no endpoint exists, there's no newer status, so return false instead of an error
|
||||
return false, nil
|
||||
}
|
||||
for _, result := range endpointStatus.(*endpoint.Status).Results {
|
||||
if result.Timestamp.After(timestamp) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Clear deletes everything from the store
|
||||
func (s *Store) Clear() {
|
||||
s.cache.Clear()
|
||||
|
||||
@@ -84,6 +84,7 @@ var (
|
||||
// This test is simply an extra sanity check
|
||||
func TestStore_SanityCheck(t *testing.T) {
|
||||
store, _ := NewStore(storage.DefaultMaximumNumberOfResults, storage.DefaultMaximumNumberOfEvents)
|
||||
defer store.Clear()
|
||||
defer store.Close()
|
||||
store.Insert(&testEndpoint, &testSuccessfulResult)
|
||||
endpointStatuses, _ := store.GetAllEndpointStatuses(paging.NewEndpointStatusParams())
|
||||
@@ -134,3 +135,30 @@ func TestStore_Save(t *testing.T) {
|
||||
store.Clear()
|
||||
store.Close()
|
||||
}
|
||||
|
||||
func TestStore_HasEndpointStatusNewerThan(t *testing.T) {
|
||||
store, _ := NewStore(storage.DefaultMaximumNumberOfResults, storage.DefaultMaximumNumberOfEvents)
|
||||
defer store.Clear()
|
||||
defer store.Close()
|
||||
// Insert a result
|
||||
err := store.Insert(&testEndpoint, &testSuccessfulResult)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error while inserting result, got %v", err)
|
||||
}
|
||||
// Check with a timestamp in the past
|
||||
hasNewerStatus, err := store.HasEndpointStatusNewerThan(testEndpoint.Key(), time.Now().Add(-time.Hour))
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if !hasNewerStatus {
|
||||
t.Fatal("expected to have a newer status, but didn't")
|
||||
}
|
||||
// Check with a timestamp in the future
|
||||
hasNewerStatus, err = store.HasEndpointStatusNewerThan(testEndpoint.Key(), time.Now().Add(time.Hour))
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if hasNewerStatus {
|
||||
t.Fatal("expected not to have a newer status, but did")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,6 +514,24 @@ func (s *Store) DeleteAllTriggeredAlertsNotInChecksumsByEndpoint(ep *endpoint.En
|
||||
return int(rowsAffects)
|
||||
}
|
||||
|
||||
// HasEndpointStatusNewerThan checks whether an endpoint has a status newer than the provided timestamp
|
||||
func (s *Store) HasEndpointStatusNewerThan(key string, timestamp time.Time) (bool, error) {
|
||||
if timestamp.IsZero() {
|
||||
return false, errors.New("timestamp is zero")
|
||||
}
|
||||
var count int
|
||||
err := s.db.QueryRow(
|
||||
"SELECT COUNT(*) FROM endpoint_results WHERE endpoint_id = (SELECT endpoint_id FROM endpoints WHERE endpoint_key = $1 LIMIT 1) AND timestamp > $2",
|
||||
key,
|
||||
timestamp.UTC(),
|
||||
).Scan(&count)
|
||||
if err != nil {
|
||||
// If the endpoint doesn't exist, we return false instead of an error
|
||||
return false, nil
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
// Clear deletes everything from the store
|
||||
func (s *Store) Clear() {
|
||||
_, _ = s.db.Exec("DELETE FROM endpoints")
|
||||
|
||||
@@ -853,3 +853,36 @@ func TestStore_DeleteAllTriggeredAlertsNotInChecksumsByEndpoint(t *testing.T) {
|
||||
t.Error("expected alert3 to exist for ep2")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_HasEndpointStatusNewerThan(t *testing.T) {
|
||||
store, _ := NewStore("sqlite", t.TempDir()+"/TestStore_HasEndpointStatusNewerThan.db", false, storage.DefaultMaximumNumberOfResults, storage.DefaultMaximumNumberOfEvents)
|
||||
defer store.Close()
|
||||
// Insert an endpoint status
|
||||
if err := store.Insert(&testEndpoint, &testSuccessfulResult); err != nil {
|
||||
t.Fatal("expected no error, got", err.Error())
|
||||
}
|
||||
// Check if it has a status newer than 1 hour ago
|
||||
hasNewerStatus, err := store.HasEndpointStatusNewerThan(testEndpoint.Key(), time.Now().Add(-time.Hour))
|
||||
if err != nil {
|
||||
t.Fatal("expected no error, got", err.Error())
|
||||
}
|
||||
if !hasNewerStatus {
|
||||
t.Error("expected to have a newer status")
|
||||
}
|
||||
// Check if it has a status newer than 2 days ago
|
||||
hasNewerStatus, err = store.HasEndpointStatusNewerThan(testEndpoint.Key(), time.Now().Add(-48*time.Hour))
|
||||
if err != nil {
|
||||
t.Fatal("expected no error, got", err.Error())
|
||||
}
|
||||
if !hasNewerStatus {
|
||||
t.Error("expected to have a newer status")
|
||||
}
|
||||
// Check if there's a status newer than 1 hour in the future (silly test, but it should work)
|
||||
hasNewerStatus, err = store.HasEndpointStatusNewerThan(testEndpoint.Key(), time.Now().Add(time.Hour))
|
||||
if err != nil {
|
||||
t.Fatal("expected no error, got", err.Error())
|
||||
}
|
||||
if hasNewerStatus {
|
||||
t.Error("expected not to have a newer status in the future")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ type Store interface {
|
||||
// This prevents triggered alerts that have been removed or modified from lingering in the database.
|
||||
DeleteAllTriggeredAlertsNotInChecksumsByEndpoint(ep *endpoint.Endpoint, checksums []string) int
|
||||
|
||||
// HasEndpointStatusNewerThan checks whether an endpoint has a status newer than the provided timestamp
|
||||
HasEndpointStatusNewerThan(key string, timestamp time.Time) (bool, error)
|
||||
|
||||
// Clear deletes everything from the store
|
||||
Clear()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user