Browse Source

Lots of progress on command/query bus concept, in memory sql testing, datasource admin

Torkel Ödegaard 11 năm trước cách đây
mục cha
commit
c7ed348ee8

+ 1 - 0
pkg/api/api_datasources.go

@@ -30,4 +30,5 @@ func AddDataSource(c *middleware.Context) {
 		return
 	}
 
+	c.Status(204)
 }

+ 0 - 2
pkg/bus/bus.go

@@ -2,7 +2,6 @@ package bus
 
 import (
 	"errors"
-	"fmt"
 	"reflect"
 )
 
@@ -50,7 +49,6 @@ func (b *InProcBus) Dispatch(msg Msg) error {
 func (b *InProcBus) AddHandler(handler HandlerFunc) {
 	handlerType := reflect.TypeOf(handler)
 	queryTypeName := handlerType.In(0).Elem().Name()
-	fmt.Printf("QueryType %v\n", queryTypeName)
 	b.handlers[queryTypeName] = handler
 }
 

+ 1 - 6
pkg/cmd/web.go

@@ -70,12 +70,7 @@ func runWeb(*cli.Context) {
 	social.NewOAuthService()
 
 	sqlstore.Init()
-
-	// init database
-	sqlstore.LoadModelsConfig()
-	if err := sqlstore.NewEngine(); err != nil {
-		log.Fatal(4, "fail to initialize orm engine: %v", err)
-	}
+	sqlstore.NewEngine()
 
 	m := newMacaron()
 	api.Register(m)

+ 3 - 2
pkg/models/account.go

@@ -37,6 +37,7 @@ type Account struct {
 	Company         string
 	NextDashboardId int
 	UsingAccountId  int64
-	Created         time.Time `xorm:"CREATED"`
-	Updated         time.Time `xorm:"UPDATED"`
+
+	Created time.Time
+	Updated time.Time
 }

+ 2 - 2
pkg/models/datasource.go

@@ -6,8 +6,8 @@ const (
 	DS_GRAPHITE      = "GRAPHITE"
 	DS_INFLUXDB      = "INFLUXDB"
 	DS_ES            = "ES"
-	DS_ACESSS_DIRECT = "DIRECT"
-	DS_ACESSS_PROXY  = "PROXY"
+	DS_ACCESS_DIRECT = "DIRECT"
+	DS_ACCESS_PROXY  = "PROXY"
 )
 
 type DsType string

+ 77 - 35
pkg/stores/sqlstore/sqlstore.go

@@ -6,6 +6,7 @@ import (
 	"path"
 	"strings"
 
+	"github.com/torkelo/grafana-pro/pkg/log"
 	m "github.com/torkelo/grafana-pro/pkg/models"
 	"github.com/torkelo/grafana-pro/pkg/setting"
 
@@ -26,10 +27,14 @@ var (
 	UseSQLite3 bool
 )
 
-func Init() {
+func init() {
+	tables = make([]interface{}, 0)
+
 	tables = append(tables, new(m.Account), new(m.Dashboard),
 		new(m.Collaborator), new(m.DataSource))
+}
 
+func Init() {
 	m.SaveAccount = SaveAccount
 	m.GetAccount = GetAccount
 	m.GetAccountByLogin = GetAccountByLogin
@@ -42,55 +47,52 @@ func Init() {
 	m.AddCollaborator = AddCollaborator
 }
 
-func LoadModelsConfig() {
-	DbCfg.Type = setting.Cfg.MustValue("database", "type")
-	if DbCfg.Type == "sqlite3" {
-		UseSQLite3 = true
-	}
-	DbCfg.Host = setting.Cfg.MustValue("database", "host")
-	DbCfg.Name = setting.Cfg.MustValue("database", "name")
-	DbCfg.User = setting.Cfg.MustValue("database", "user")
-	if len(DbCfg.Pwd) == 0 {
-		DbCfg.Pwd = setting.Cfg.MustValue("database", "password")
-	}
-	DbCfg.SslMode = setting.Cfg.MustValue("database", "ssl_mode")
-	DbCfg.Path = setting.Cfg.MustValue("database", "path", "data/grafana.db")
-}
-
 func NewEngine() (err error) {
-	if err = SetEngine(); err != nil {
-		return err
+	x, err = getEngine()
+
+	if err != nil {
+		return fmt.Errorf("sqlstore.init(fail to connect to database): %v", err)
 	}
-	if err = x.Sync2(tables...); err != nil {
-		return fmt.Errorf("sync database struct error: %v\n", err)
+
+	err = SetEngine(x, true)
+
+	if err != nil {
+		log.Fatal(4, "fail to initialize orm engine: %v", err)
 	}
+
 	return nil
 }
 
-func SetEngine() (err error) {
-	x, err = getEngine()
-	if err != nil {
-		return fmt.Errorf("models.init(fail to connect to database): %v", err)
+func SetEngine(engine *xorm.Engine, enableLog bool) (err error) {
+	x = engine
+
+	if err := x.Sync2(tables...); err != nil {
+		return fmt.Errorf("sync database struct error: %v\n", err)
 	}
 
-	logPath := path.Join(setting.LogRootPath, "xorm.log")
-	os.MkdirAll(path.Dir(logPath), os.ModePerm)
+	if enableLog {
+		logPath := path.Join(setting.LogRootPath, "xorm.log")
+		os.MkdirAll(path.Dir(logPath), os.ModePerm)
 
-	f, err := os.Create(logPath)
-	if err != nil {
-		return fmt.Errorf("models.init(fail to create xorm.log): %v", err)
+		f, err := os.Create(logPath)
+		if err != nil {
+			return fmt.Errorf("sqlstore.init(fail to create xorm.log): %v", err)
+		}
+		x.Logger = xorm.NewSimpleLogger(f)
+
+		x.ShowSQL = true
+		x.ShowInfo = true
+		x.ShowDebug = true
+		x.ShowErr = true
+		x.ShowWarn = true
 	}
-	x.Logger = xorm.NewSimpleLogger(f)
 
-	x.ShowSQL = true
-	x.ShowInfo = true
-	x.ShowDebug = true
-	x.ShowErr = true
-	x.ShowWarn = true
 	return nil
 }
 
 func getEngine() (*xorm.Engine, error) {
+	LoadConfig()
+
 	cnnstr := ""
 	switch DbCfg.Type {
 	case "mysql":
@@ -113,5 +115,45 @@ func getEngine() (*xorm.Engine, error) {
 	default:
 		return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type)
 	}
+
 	return xorm.NewEngine(DbCfg.Type, cnnstr)
 }
+
+func LoadConfig() {
+	DbCfg.Type = setting.Cfg.MustValue("database", "type")
+	if DbCfg.Type == "sqlite3" {
+		UseSQLite3 = true
+	}
+	DbCfg.Host = setting.Cfg.MustValue("database", "host")
+	DbCfg.Name = setting.Cfg.MustValue("database", "name")
+	DbCfg.User = setting.Cfg.MustValue("database", "user")
+	if len(DbCfg.Pwd) == 0 {
+		DbCfg.Pwd = setting.Cfg.MustValue("database", "password")
+	}
+	DbCfg.SslMode = setting.Cfg.MustValue("database", "ssl_mode")
+	DbCfg.Path = setting.Cfg.MustValue("database", "path", "data/grafana.db")
+}
+
+type dbTransactionFunc func(sess *xorm.Session) error
+
+func inTransaction(callback dbTransactionFunc) error {
+	var err error
+
+	sess := x.NewSession()
+	defer sess.Close()
+
+	if err = sess.Begin(); err != nil {
+		return err
+	}
+
+	err = callback(sess)
+
+	if err != nil {
+		sess.Rollback()
+		return err
+	} else if err = sess.Commit(); err != nil {
+		return err
+	}
+
+	return nil
+}

+ 32 - 5
pkg/stores/sqlstore/sqlstore_datasource.go

@@ -1,20 +1,47 @@
 package sqlstore
 
 import (
-	"errors"
+	"time"
+
 	"github.com/torkelo/grafana-pro/pkg/bus"
 	m "github.com/torkelo/grafana-pro/pkg/models"
+
+	"github.com/go-xorm/xorm"
 )
 
 func init() {
-	bus.AddHandler("sql", GetDataSourcesQuery)
+	bus.AddHandler("sql", GetDataSources)
 	bus.AddHandler("sql", AddDataSource)
 }
 
-func GetDataSourcesQuery(query *m.GetDataSourcesQuery) error {
-	return errors.New("Hello from query handler")
+func GetDataSources(query *m.GetDataSourcesQuery) error {
+	sess := x.Limit(100, 0).Where("account_id=?", query.AccountId)
+
+	query.Resp = make([]*m.DataSource, 0)
+	return sess.Find(&query.Resp)
 }
 
 func AddDataSource(cmd *m.AddDataSourceCommand) error {
-	return errors.New("Hello from command handler")
+
+	return inTransaction(func(sess *xorm.Session) error {
+		var err error
+
+		ds := m.DataSource{
+			AccountId: cmd.AccountId,
+			Name:      cmd.Name,
+			Type:      cmd.Type,
+			Access:    cmd.Access,
+			Url:       cmd.Url,
+			Created:   time.Now(),
+			Updated:   time.Now(),
+		}
+
+		if ds.Id == 0 {
+			_, err = sess.Insert(ds)
+		} else {
+			_, err = sess.Id(ds.Id).Update(ds)
+		}
+
+		return err
+	})
 }

+ 54 - 0
pkg/stores/sqlstore/sqlstore_test.go

@@ -0,0 +1,54 @@
+package sqlstore
+
+import (
+	"testing"
+
+	"github.com/go-xorm/xorm"
+
+	. "github.com/smartystreets/goconvey/convey"
+
+	m "github.com/torkelo/grafana-pro/pkg/models"
+)
+
+func InitTestDB(t *testing.T) {
+	x, err := xorm.NewEngine("sqlite3", ":memory:")
+
+	if err != nil {
+		t.Fatalf("Failed to init in memory sqllite3 db %v", err)
+	}
+
+	SetEngine(x, false)
+}
+
+type Test struct {
+	Id   int64
+	Name string
+}
+
+func TestDataAccess(t *testing.T) {
+
+	Convey("Testing DB", t, func() {
+		InitTestDB(t)
+
+		Convey("Can add datasource", func() {
+
+			err := AddDataSource(&m.AddDataSourceCommand{
+				AccountId: 10,
+				Type:      m.DS_GRAPHITE,
+				Access:    m.DS_ACCESS_DIRECT,
+				Url:       "http://test",
+			})
+
+			So(err, ShouldBeNil)
+
+			query := m.GetDataSourcesQuery{AccountId: 10}
+			err = GetDataSources(&query)
+			So(err, ShouldBeNil)
+
+			So(len(query.Resp), ShouldEqual, 1)
+
+		})
+
+	})
+
+}