remove global variable in annotation (#46746)

* remove global varaible in annotation

* remove todo

* replace intransaction with withdbtransaction

* fix typo
This commit is contained in:
ying-jeanne
2022-03-22 19:20:57 +08:00
committed by GitHub
parent 3d43535bc3
commit adc0cbf176
8 changed files with 157 additions and 152 deletions
+117 -112
View File
@@ -2,6 +2,7 @@ package sqlstore
import (
"bytes"
"context"
"errors"
"fmt"
"strings"
@@ -29,6 +30,7 @@ func validateTimeRange(item *annotations.Item) error {
}
type SQLAnnotationRepo struct {
sql *SQLStore
}
func (r *SQLAnnotationRepo) Save(item *annotations.Item) error {
@@ -64,8 +66,8 @@ func (r *SQLAnnotationRepo) Save(item *annotations.Item) error {
})
}
func (r *SQLAnnotationRepo) Update(item *annotations.Item) error {
return inTransaction(func(sess *DBSession) error {
func (r *SQLAnnotationRepo) Update(ctx context.Context, item *annotations.Item) error {
return r.sql.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
var (
isExist bool
err error
@@ -117,121 +119,124 @@ func (r *SQLAnnotationRepo) Update(item *annotations.Item) error {
})
}
func (r *SQLAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
func (r *SQLAnnotationRepo) Find(ctx context.Context, query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
var sql bytes.Buffer
params := make([]interface{}, 0)
sql.WriteString(`
SELECT
annotation.id,
annotation.epoch as time,
annotation.epoch_end as time_end,
annotation.dashboard_id,
annotation.panel_id,
annotation.new_state,
annotation.prev_state,
annotation.alert_id,
annotation.text,
annotation.tags,
annotation.data,
annotation.created,
annotation.updated,
usr.email,
usr.login,
alert.name as alert_name
FROM annotation
LEFT OUTER JOIN ` + dialect.Quote("user") + ` as usr on usr.id = annotation.user_id
LEFT OUTER JOIN alert on alert.id = annotation.alert_id
INNER JOIN (
SELECT a.id from annotation a
`)
sql.WriteString(`WHERE a.org_id = ?`)
params = append(params, query.OrgId)
if query.AnnotationId != 0 {
// fmt.Print("annotation query")
sql.WriteString(` AND a.id = ?`)
params = append(params, query.AnnotationId)
}
if query.AlertId != 0 {
sql.WriteString(` AND a.alert_id = ?`)
params = append(params, query.AlertId)
}
if query.DashboardId != 0 {
sql.WriteString(` AND a.dashboard_id = ?`)
params = append(params, query.DashboardId)
}
if query.PanelId != 0 {
sql.WriteString(` AND a.panel_id = ?`)
params = append(params, query.PanelId)
}
if query.UserId != 0 {
sql.WriteString(` AND a.user_id = ?`)
params = append(params, query.UserId)
}
if query.From > 0 && query.To > 0 {
sql.WriteString(` AND a.epoch <= ? AND a.epoch_end >= ?`)
params = append(params, query.To, query.From)
}
if query.Type == "alert" {
sql.WriteString(` AND a.alert_id > 0`)
} else if query.Type == "annotation" {
sql.WriteString(` AND a.alert_id = 0`)
}
if len(query.Tags) > 0 {
keyValueFilters := []string{}
tags := models.ParseTagPairs(query.Tags)
for _, tag := range tags {
if tag.Value == "" {
keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ?)")
params = append(params, tag.Key)
} else {
keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ? AND tag."+dialect.Quote("value")+" = ?)")
params = append(params, tag.Key, tag.Value)
}
}
if len(tags) > 0 {
tagsSubQuery := fmt.Sprintf(`
SELECT SUM(1) FROM annotation_tag at
INNER JOIN tag on tag.id = at.tag_id
WHERE at.annotation_id = a.id
AND (
%s
)
`, strings.Join(keyValueFilters, " OR "))
if query.MatchAny {
sql.WriteString(fmt.Sprintf(" AND (%s) > 0 ", tagsSubQuery))
} else {
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
}
}
}
if query.Limit == 0 {
query.Limit = 100
}
// order of ORDER BY arguments match the order of a sql index for performance
sql.WriteString(" ORDER BY a.org_id, a.epoch_end DESC, a.epoch DESC" + dialect.Limit(query.Limit) + " ) dt on dt.id = annotation.id")
items := make([]*annotations.ItemDTO, 0)
err := r.sql.WithDbSession(ctx, func(sess *DBSession) error {
sql.WriteString(`
SELECT
annotation.id,
annotation.epoch as time,
annotation.epoch_end as time_end,
annotation.dashboard_id,
annotation.panel_id,
annotation.new_state,
annotation.prev_state,
annotation.alert_id,
annotation.text,
annotation.tags,
annotation.data,
annotation.created,
annotation.updated,
usr.email,
usr.login,
alert.name as alert_name
FROM annotation
LEFT OUTER JOIN ` + dialect.Quote("user") + ` as usr on usr.id = annotation.user_id
LEFT OUTER JOIN alert on alert.id = annotation.alert_id
INNER JOIN (
SELECT a.id from annotation a
`)
if err := x.SQL(sql.String(), params...).Find(&items); err != nil {
return nil, err
}
sql.WriteString(`WHERE a.org_id = ?`)
params = append(params, query.OrgId)
return items, nil
if query.AnnotationId != 0 {
// fmt.Print("annotation query")
sql.WriteString(` AND a.id = ?`)
params = append(params, query.AnnotationId)
}
if query.AlertId != 0 {
sql.WriteString(` AND a.alert_id = ?`)
params = append(params, query.AlertId)
}
if query.DashboardId != 0 {
sql.WriteString(` AND a.dashboard_id = ?`)
params = append(params, query.DashboardId)
}
if query.PanelId != 0 {
sql.WriteString(` AND a.panel_id = ?`)
params = append(params, query.PanelId)
}
if query.UserId != 0 {
sql.WriteString(` AND a.user_id = ?`)
params = append(params, query.UserId)
}
if query.From > 0 && query.To > 0 {
sql.WriteString(` AND a.epoch <= ? AND a.epoch_end >= ?`)
params = append(params, query.To, query.From)
}
if query.Type == "alert" {
sql.WriteString(` AND a.alert_id > 0`)
} else if query.Type == "annotation" {
sql.WriteString(` AND a.alert_id = 0`)
}
if len(query.Tags) > 0 {
keyValueFilters := []string{}
tags := models.ParseTagPairs(query.Tags)
for _, tag := range tags {
if tag.Value == "" {
keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ?)")
params = append(params, tag.Key)
} else {
keyValueFilters = append(keyValueFilters, "(tag."+dialect.Quote("key")+" = ? AND tag."+dialect.Quote("value")+" = ?)")
params = append(params, tag.Key, tag.Value)
}
}
if len(tags) > 0 {
tagsSubQuery := fmt.Sprintf(`
SELECT SUM(1) FROM annotation_tag at
INNER JOIN tag on tag.id = at.tag_id
WHERE at.annotation_id = a.id
AND (
%s
)
`, strings.Join(keyValueFilters, " OR "))
if query.MatchAny {
sql.WriteString(fmt.Sprintf(" AND (%s) > 0 ", tagsSubQuery))
} else {
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
}
}
}
if query.Limit == 0 {
query.Limit = 100
}
// order of ORDER BY arguments match the order of a sql index for performance
sql.WriteString(" ORDER BY a.org_id, a.epoch_end DESC, a.epoch DESC" + dialect.Limit(query.Limit) + " ) dt on dt.id = annotation.id")
if err := sess.SQL(sql.String(), params...).Find(&items); err != nil {
items = nil
return err
}
return nil
},
)
return items, err
}
func (r *SQLAnnotationRepo) Delete(params *annotations.DeleteParams) error {
+22 -22
View File
@@ -4,10 +4,10 @@
package sqlstore
import (
"testing"
"context"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"github.com/grafana/grafana/pkg/services/annotations"
)
@@ -15,8 +15,9 @@ import (
func TestAnnotations(t *testing.T) {
mockTimeNow()
defer resetTimeNow()
InitTestDB(t)
repo := SQLAnnotationRepo{}
repo.sql = InitTestDB(t)
t.Run("Testing annotation create, read, update and delete", func(t *testing.T) {
t.Cleanup(func() {
@@ -79,9 +80,8 @@ func TestAnnotations(t *testing.T) {
err = repo.Save(globalAnnotation2)
require.NoError(t, err)
assert.Greater(t, globalAnnotation2.Id, int64(0))
t.Run("Can query for annotation by dashboard id", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 0,
@@ -99,7 +99,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Can query for annotation by id", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
AnnotationId: annotation2.Id,
})
@@ -109,7 +109,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should not find any when item is outside time range", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 12,
@@ -120,7 +120,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should not find one when tag filter does not match", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 1,
@@ -132,7 +132,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should not find one when type filter does not match", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 1,
@@ -144,7 +144,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should find one when all tag filters does match", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 1,
@@ -156,7 +156,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should find two annotations using partial match", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
From: 1,
To: 25,
@@ -168,7 +168,7 @@ func TestAnnotations(t *testing.T) {
})
t.Run("Should find one when all key value tag filters does match", func(t *testing.T) {
items, err := repo.Find(&annotations.ItemQuery{
items, err := repo.Find(context.Background(), &annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
From: 1,
@@ -186,11 +186,11 @@ func TestAnnotations(t *testing.T) {
From: 0,
To: 15,
}
items, err := repo.Find(query)
items, err := repo.Find(context.Background(), query)
require.NoError(t, err)
annotationId := items[0].Id
err = repo.Update(&annotations.Item{
err = repo.Update(context.Background(), &annotations.Item{
Id: annotationId,
OrgId: 1,
Text: "something new",
@@ -198,7 +198,7 @@ func TestAnnotations(t *testing.T) {
})
require.NoError(t, err)
items, err = repo.Find(query)
items, err = repo.Find(context.Background(), query)
require.NoError(t, err)
assert.Equal(t, annotationId, items[0].Id)
@@ -213,11 +213,11 @@ func TestAnnotations(t *testing.T) {
From: 0,
To: 15,
}
items, err := repo.Find(query)
items, err := repo.Find(context.Background(), query)
require.NoError(t, err)
annotationId := items[0].Id
err = repo.Update(&annotations.Item{
err = repo.Update(context.Background(), &annotations.Item{
Id: annotationId,
OrgId: 1,
Text: "something new",
@@ -225,7 +225,7 @@ func TestAnnotations(t *testing.T) {
})
require.NoError(t, err)
items, err = repo.Find(query)
items, err = repo.Find(context.Background(), query)
require.NoError(t, err)
assert.Equal(t, annotationId, items[0].Id)
@@ -241,14 +241,14 @@ func TestAnnotations(t *testing.T) {
From: 0,
To: 15,
}
items, err := repo.Find(query)
items, err := repo.Find(context.Background(), query)
require.NoError(t, err)
annotationId := items[0].Id
err = repo.Delete(&annotations.DeleteParams{Id: annotationId, OrgId: 1})
require.NoError(t, err)
items, err = repo.Find(query)
items, err = repo.Find(context.Background(), query)
require.NoError(t, err)
assert.Empty(t, items)
})
@@ -270,7 +270,7 @@ func TestAnnotations(t *testing.T) {
OrgId: 1,
AnnotationId: annotation3.Id,
}
items, err := repo.Find(query)
items, err := repo.Find(context.Background(), query)
require.NoError(t, err)
dashboardId := items[0].DashboardId
@@ -278,7 +278,7 @@ func TestAnnotations(t *testing.T) {
err = repo.Delete(&annotations.DeleteParams{DashboardId: dashboardId, PanelId: panelId, OrgId: 1})
require.NoError(t, err)
items, err = repo.Find(query)
items, err = repo.Find(context.Background(), query)
require.NoError(t, err)
assert.Empty(t, items)
})
+1 -1
View File
@@ -109,7 +109,7 @@ func newSQLStore(cfg *setting.Cfg, cacheService *localcache.CacheService, b bus.
dialect = ss.Dialect
// Init repo instances
annotations.SetRepository(&SQLAnnotationRepo{})
annotations.SetRepository(&SQLAnnotationRepo{sql: ss})
annotations.SetAnnotationCleaner(&AnnotationCleanupService{batchSize: ss.Cfg.AnnotationCleanupJobBatchSize, log: log.New("annotationcleaner")})
ss.Bus.SetTransactionManager(ss)