Skip to content

Commit 68b280c

Browse files
julianbrostyhabteab
authored andcommitted
Deduplicate Restore(Muted)Objects common codes
1 parent 48ccc56 commit 68b280c

File tree

2 files changed

+36
-58
lines changed

2 files changed

+36
-58
lines changed

internal/object/object.go

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"github.com/icinga/icinga-go-library/types"
1414
"github.com/icinga/icinga-notifications/internal/event"
1515
"github.com/icinga/icinga-notifications/internal/utils"
16-
"github.com/pkg/errors"
1716
"regexp"
1817
"sort"
1918
"strings"
@@ -67,42 +66,6 @@ func ClearCache() {
6766
cache = make(map[string]*Object)
6867
}
6968

70-
// RestoreObjects restores all objects and their (extra)tags matching the given IDs from the database.
71-
// Returns error on any database failures and panics when trying to cache an object that's already in the cache store.
72-
func RestoreObjects(ctx context.Context, db *database.DB, ids []types.Binary) error {
73-
objects := map[string]*Object{}
74-
err := utils.ForEachRow[Object](ctx, db, "id", ids, func(o *Object) {
75-
o.db = db
76-
o.Tags = map[string]string{}
77-
o.ExtraTags = map[string]string{}
78-
79-
objects[o.ID.String()] = o
80-
})
81-
if err != nil {
82-
return errors.Wrap(err, "cannot restore objects")
83-
}
84-
85-
// Restore object ID tags matching the given object ids
86-
err = utils.ForEachRow[IdTagRow](ctx, db, "object_id", ids, func(ir *IdTagRow) {
87-
objects[ir.ObjectId.String()].Tags[ir.Tag] = ir.Value
88-
})
89-
if err != nil {
90-
return errors.Wrap(err, "cannot restore objects ID tags")
91-
}
92-
93-
// Restore object extra tags matching the given object ids
94-
err = utils.ForEachRow[ExtraTagRow](ctx, db, "object_id", ids, func(et *ExtraTagRow) {
95-
objects[et.ObjectId.String()].ExtraTags[et.Tag] = et.Value
96-
})
97-
if err != nil {
98-
return errors.Wrap(err, "cannot restore objects extra tags")
99-
}
100-
101-
addObjectsToCache(objects)
102-
103-
return nil
104-
}
105-
10669
// FromEvent creates an object from the provided event tags if it's not in the cache
10770
// and syncs all object related types with the database.
10871
// Returns error on any database failure

internal/object/objects.go

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/icinga/icinga-go-library/database"
88
"github.com/icinga/icinga-go-library/types"
99
"github.com/icinga/icinga-notifications/internal/utils"
10+
"github.com/jmoiron/sqlx"
1011
"github.com/pkg/errors"
1112
"golang.org/x/sync/errgroup"
1213
"sync"
@@ -30,14 +31,34 @@ func DeleteFromCache(id types.Binary) {
3031
//
3132
// Returns an error on any database failure and panics when trying to cache an object that's already in the cache store.
3233
func RestoreMutedObjects(ctx context.Context, db *database.DB) error {
34+
query := db.BuildSelectStmt(new(Object), new(Object)) + " WHERE mute_reason IS NOT NULL " +
35+
"AND NOT EXISTS((SELECT 1 FROM incident WHERE object_id = object.id AND recovered_at IS NULL))"
36+
return restoreObjectsFromQuery(ctx, db, query)
37+
}
38+
39+
// RestoreObjects restores all objects and their (extra)tags matching the given IDs from the database.
40+
// Returns error on any database failures and panics when trying to cache an object that's already in the cache store.
41+
func RestoreObjects(ctx context.Context, db *database.DB, ids []types.Binary) error {
42+
var obj *Object
43+
query, args, err := sqlx.In(db.BuildSelectStmt(obj, obj)+" WHERE id IN (?)", ids)
44+
if err != nil {
45+
return errors.Wrapf(err, "cannot build placeholders for %q", query)
46+
}
47+
48+
return restoreObjectsFromQuery(ctx, db, query, args...)
49+
}
50+
51+
// restoreObjectsFromQuery takes a query that returns rows of the object table, executes it and loads the returned
52+
// objects into the local cache.
53+
//
54+
// Returns an error on any database failure and panics when trying to cache an object that's already in the cache store.
55+
func restoreObjectsFromQuery(ctx context.Context, db *database.DB, query string, args ...any) error {
3356
objects := make(chan *Object)
3457
g, ctx := errgroup.WithContext(ctx)
3558
g.Go(func() error {
3659
defer close(objects)
3760

38-
clause := `WHERE mute_reason IS NOT NULL AND NOT EXISTS((SELECT 1 FROM incident WHERE object_id = object.id AND recovered_at IS NULL))`
39-
query := fmt.Sprintf("%s %s", db.BuildSelectStmt(new(Object), new(Object)), clause)
40-
err := utils.ExecAndApply[Object](ctx, db, query, nil, func(o *Object) {
61+
err := utils.ExecAndApply[Object](ctx, db, query, args, func(o *Object) {
4162
o.db = db
4263
o.Tags = map[string]string{}
4364
o.ExtraTags = map[string]string{}
@@ -64,8 +85,8 @@ func RestoreMutedObjects(ctx context.Context, db *database.DB) error {
6485
}
6586

6687
g.Go(func() error {
67-
var ids []types.Binary
68-
objectsMap := map[string]*Object{}
88+
ids := make([]types.Binary, 0, len(bulk))
89+
objectsMap := make(map[string]*Object, len(bulk))
6990
for _, obj := range bulk {
7091
objectsMap[obj.ID.String()] = obj
7192
ids = append(ids, obj.ID)
@@ -87,7 +108,16 @@ func RestoreMutedObjects(ctx context.Context, db *database.DB) error {
87108
return errors.Wrap(err, "cannot restore objects extra tags")
88109
}
89110

90-
addObjectsToCache(objectsMap)
111+
cacheMu.Lock()
112+
defer cacheMu.Unlock()
113+
114+
for _, o := range objectsMap {
115+
if obj, ok := cache[o.ID.String()]; ok {
116+
panic(fmt.Sprintf("Object %q is already in the cache", obj.DisplayName()))
117+
}
118+
119+
cache[o.ID.String()] = o
120+
}
91121

92122
return nil
93123
})
@@ -97,18 +127,3 @@ func RestoreMutedObjects(ctx context.Context, db *database.DB) error {
97127

98128
return g.Wait()
99129
}
100-
101-
// addObjectsToCache adds the objects from the given map to the global object cache store.
102-
// Panics when trying to cache an object that's already in the cache store.
103-
func addObjectsToCache(objects map[string]*Object) {
104-
cacheMu.Lock()
105-
defer cacheMu.Unlock()
106-
107-
for _, o := range objects {
108-
if obj, ok := cache[o.ID.String()]; ok {
109-
panic(fmt.Sprintf("Object %q is already in the cache", obj.DisplayName()))
110-
}
111-
112-
cache[o.ID.String()] = o
113-
}
114-
}

0 commit comments

Comments
 (0)