grafana/pkg/services/ngalert/store/provisioning_store.go
Kristin Laemmert 05709ce411
chore: remove sqlstore & mockstore dependencies from (most) packages (#57087)
* chore: add alias for InitTestDB and Session

Adds an alias for the sqlstore InitTestDB and Session, and updates tests using these to reduce dependencies on the sqlstore.Store.

* next pass of removing sqlstore imports
* last little bit
* remove mockstore where possible
2022-10-19 09:02:15 -04:00

106 lines
3.6 KiB
Go

package store
import (
"context"
"fmt"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
type provenanceRecord struct {
Id int `xorm:"pk autoincr 'id'"`
OrgID int64 `xorm:"'org_id'"`
RecordKey string
RecordType string
Provenance models.Provenance
}
func (pr provenanceRecord) TableName() string {
return "provenance_type"
}
// GetProvenance gets the provenance status for a provisionable object.
func (st DBstore) GetProvenance(ctx context.Context, o models.Provisionable, org int64) (models.Provenance, error) {
recordType := o.ResourceType()
recordKey := o.ResourceID()
provenance := models.ProvenanceNone
err := st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
filter := "record_key = ? AND record_type = ? AND org_id = ?"
var result models.Provenance
has, err := sess.Table(provenanceRecord{}).Where(filter, recordKey, recordType, org).Desc("id").Cols("provenance").Get(&result)
if err != nil {
return fmt.Errorf("failed to query for existing provenance status: %w", err)
}
if has {
provenance = result
}
return nil
})
if err != nil {
return models.ProvenanceNone, err
}
return provenance, nil
}
// GetProvenance gets the provenance status for a provisionable object.
func (st DBstore) GetProvenances(ctx context.Context, org int64, resourceType string) (map[string]models.Provenance, error) {
resultMap := make(map[string]models.Provenance)
err := st.SQLStore.WithDbSession(ctx, func(sess *db.Session) error {
filter := "record_type = ? AND org_id = ?"
rawData, err := sess.Table(provenanceRecord{}).Where(filter, resourceType, org).Desc("id").Cols("record_key", "provenance").QueryString()
if err != nil {
return fmt.Errorf("failed to query for existing provenance status: %w", err)
}
for _, data := range rawData {
resultMap[data["record_key"]] = models.Provenance(data["provenance"])
}
return nil
})
return resultMap, err
}
// SetProvenance changes the provenance status for a provisionable object.
func (st DBstore) SetProvenance(ctx context.Context, o models.Provisionable, org int64, p models.Provenance) error {
recordType := o.ResourceType()
recordKey := o.ResourceID()
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
// TODO: Add a unit-of-work pattern, so updating objects + provenance will happen consistently with rollbacks across stores.
// TODO: Need to make sure that writing a record where our concurrency key fails will also fail the whole transaction. That way, this gets rolled back too. can't just check that 0 updates happened inmemory. Check with jp. If not possible, we need our own concurrency key.
// TODO: Clean up stale provenance records periodically.
filter := "record_key = ? AND record_type = ? AND org_id = ?"
_, err := sess.Table(provenanceRecord{}).Where(filter, recordKey, recordType, org).Delete(provenanceRecord{})
if err != nil {
return fmt.Errorf("failed to delete pre-existing provisioning status: %w", err)
}
record := provenanceRecord{
RecordKey: recordKey,
RecordType: recordType,
Provenance: p,
OrgID: org,
}
if _, err := sess.Insert(record); err != nil {
return fmt.Errorf("failed to store provisioning status: %w", err)
}
return nil
})
}
// DeleteProvenance deletes the provenance record from the table
func (st DBstore) DeleteProvenance(ctx context.Context, o models.Provisionable, org int64) error {
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
_, err := sess.Delete(provenanceRecord{
RecordKey: o.ResourceID(),
RecordType: o.ResourceType(),
OrgID: org,
})
return err
})
}