mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 04:50:54 +00:00
Merge develop-2.0
This commit is contained in:
commit
f73eee75ff
@ -16,15 +16,15 @@ package beego
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
BuildVersion string
|
BuildVersion string
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
BuildGitRevision string
|
BuildGitRevision string
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
BuildStatus string
|
BuildStatus string
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
BuildTag string
|
BuildTag string
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
BuildTime string
|
BuildTime string
|
||||||
|
|
||||||
// Deprecated: using pkg/, we will delete this in v2.1.0
|
// Deprecated: using pkg/, we will delete this in v2.1.0
|
||||||
GoVersion string
|
GoVersion string
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"crypto/tls"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/config"
|
"github.com/astaxie/beego/config"
|
||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
@ -163,7 +163,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
appConfigPath = filepath.Join(WorkPath, "conf", filename)
|
appConfigPath = filepath.Join(WorkPath, "conf", filename)
|
||||||
if configPath := os.Getenv("BEEGO_CONFIG_PATH"); configPath != "" {
|
if configPath := os.Getenv("BEEGO_CONFIG_PATH"); configPath != "" {
|
||||||
appConfigPath = configPath
|
appConfigPath = configPath
|
||||||
}
|
}
|
||||||
if !utils.FileExists(appConfigPath) {
|
if !utils.FileExists(appConfigPath) {
|
||||||
appConfigPath = filepath.Join(AppPath, "conf", filename)
|
appConfigPath = filepath.Join(AppPath, "conf", filename)
|
||||||
|
@ -51,9 +51,9 @@ import (
|
|||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
type Configer interface {
|
type Configer interface {
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
Set(key, val string) error //support section::key type in given key when using ini type.
|
Set(key, val string) error //support section::key type in given key when using ini type.
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
|
String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
Strings(key string) []string //get string slice
|
Strings(key string) []string //get string slice
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
@ -65,7 +65,7 @@ type Configer interface {
|
|||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
Float(key string) (float64, error)
|
Float(key string) (float64, error)
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
|
DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
DefaultStrings(key string, defaultVal []string) []string //get string slice
|
DefaultStrings(key string, defaultVal []string) []string //get string slice
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
|
@ -27,15 +27,18 @@ type fakeConfigContainer struct {
|
|||||||
func (c *fakeConfigContainer) getData(key string) string {
|
func (c *fakeConfigContainer) getData(key string) string {
|
||||||
return c.data[strings.ToLower(key)]
|
return c.data[strings.ToLower(key)]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Set(key, val string) error {
|
func (c *fakeConfigContainer) Set(key, val string) error {
|
||||||
c.data[strings.ToLower(key)] = val
|
c.data[strings.ToLower(key)] = val
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) String(key string) string {
|
func (c *fakeConfigContainer) String(key string) string {
|
||||||
return c.getData(key)
|
return c.getData(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string {
|
func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string {
|
||||||
v := c.String(key)
|
v := c.String(key)
|
||||||
@ -44,6 +47,7 @@ func (c *fakeConfigContainer) DefaultString(key string, defaultval string) strin
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Strings(key string) []string {
|
func (c *fakeConfigContainer) Strings(key string) []string {
|
||||||
v := c.String(key)
|
v := c.String(key)
|
||||||
@ -52,6 +56,7 @@ func (c *fakeConfigContainer) Strings(key string) []string {
|
|||||||
}
|
}
|
||||||
return strings.Split(v, ";")
|
return strings.Split(v, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string {
|
||||||
v := c.Strings(key)
|
v := c.Strings(key)
|
||||||
@ -60,10 +65,12 @@ func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Int(key string) (int, error) {
|
func (c *fakeConfigContainer) Int(key string) (int, error) {
|
||||||
return strconv.Atoi(c.getData(key))
|
return strconv.Atoi(c.getData(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
|
func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
|
||||||
v, err := c.Int(key)
|
v, err := c.Int(key)
|
||||||
@ -72,10 +79,12 @@ func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Int64(key string) (int64, error) {
|
func (c *fakeConfigContainer) Int64(key string) (int64, error) {
|
||||||
return strconv.ParseInt(c.getData(key), 10, 64)
|
return strconv.ParseInt(c.getData(key), 10, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
||||||
v, err := c.Int64(key)
|
v, err := c.Int64(key)
|
||||||
@ -84,10 +93,12 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Bool(key string) (bool, error) {
|
func (c *fakeConfigContainer) Bool(key string) (bool, error) {
|
||||||
return ParseBool(c.getData(key))
|
return ParseBool(c.getData(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
||||||
v, err := c.Bool(key)
|
v, err := c.Bool(key)
|
||||||
@ -96,10 +107,12 @@ func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) Float(key string) (float64, error) {
|
func (c *fakeConfigContainer) Float(key string) (float64, error) {
|
||||||
return strconv.ParseFloat(c.getData(key), 64)
|
return strconv.ParseFloat(c.getData(key), 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
|
||||||
v, err := c.Float(key)
|
v, err := c.Float(key)
|
||||||
@ -108,6 +121,7 @@ func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
|
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
|
||||||
if v, ok := c.data[strings.ToLower(key)]; ok {
|
if v, ok := c.data[strings.ToLower(key)]; ok {
|
||||||
@ -115,10 +129,12 @@ func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
return nil, errors.New("key not find")
|
return nil, errors.New("key not find")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) {
|
func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) {
|
||||||
return nil, errors.New("not implement in the fakeConfigContainer")
|
return nil, errors.New("not implement in the fakeConfigContainer")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
// Deprecated: using pkg/config, we will delete this in v2.1.0
|
||||||
func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
|
func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
|
||||||
return errors.New("not implement in the fakeConfigContainer")
|
return errors.New("not implement in the fakeConfigContainer")
|
||||||
|
@ -58,7 +58,6 @@ func (output *BeegoOutput) Clear() {
|
|||||||
output.Status = 0
|
output.Status = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Header sets response header item string via given key.
|
// Header sets response header item string via given key.
|
||||||
func (output *BeegoOutput) Header(key, val string) {
|
func (output *BeegoOutput) Header(key, val string) {
|
||||||
output.Context.ResponseWriter.Header().Set(key, val)
|
output.Context.ResponseWriter.Header().Set(key, val)
|
||||||
|
4
go.mod
4
go.mod
@ -14,6 +14,7 @@ require (
|
|||||||
github.com/elazarl/go-bindata-assetfs v1.0.0
|
github.com/elazarl/go-bindata-assetfs v1.0.0
|
||||||
github.com/go-kit/kit v0.9.0
|
github.com/go-kit/kit v0.9.0
|
||||||
github.com/go-redis/redis v6.14.2+incompatible
|
github.com/go-redis/redis v6.14.2+incompatible
|
||||||
|
github.com/go-redis/redis/v7 v7.4.0
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
github.com/gogo/protobuf v1.1.1
|
github.com/gogo/protobuf v1.1.1
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
||||||
@ -24,6 +25,7 @@ require (
|
|||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||||
github.com/opentracing/opentracing-go v1.2.0
|
github.com/opentracing/opentracing-go v1.2.0
|
||||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.7.0
|
github.com/prometheus/client_golang v1.7.0
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644
|
||||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
|
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
|
||||||
@ -31,11 +33,9 @@ require (
|
|||||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
|
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
|
||||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
|
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
|
|
||||||
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c
|
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c
|
||||||
google.golang.org/grpc v1.31.0 // indirect
|
google.golang.org/grpc v1.31.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
replace golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 => github.com/golang/crypto v0.0.0-20181127143415-eb0de9b17e85
|
replace golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 => github.com/golang/crypto v0.0.0-20181127143415-eb0de9b17e85
|
||||||
|
12
go.sum
12
go.sum
@ -59,6 +59,8 @@ github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80n
|
|||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0=
|
github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0=
|
||||||
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
|
github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
|
||||||
|
github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||||
@ -121,8 +123,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||||
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||||
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||||
@ -197,8 +201,9 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
|||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -212,16 +217,21 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c h1:FodBYPZKH5tAN2O60HlglMwXGAeV/4k+NKbli79M/2c=
|
||||||
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
@ -6,10 +6,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/astaxie/beego/pkg/toolbox"
|
"github.com/astaxie/beego/pkg/toolbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -230,10 +231,19 @@ func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
|
|||||||
t.Errorf("invalid response map length: got %d want %d",
|
t.Errorf("invalid response map length: got %d want %d",
|
||||||
len(decodedResponseBody), len(expectedResponseBody))
|
len(decodedResponseBody), len(expectedResponseBody))
|
||||||
}
|
}
|
||||||
|
assert.Equal(t, len(expectedResponseBody), len(decodedResponseBody))
|
||||||
|
assert.Equal(t, 2, len(decodedResponseBody))
|
||||||
|
|
||||||
if !reflect.DeepEqual(decodedResponseBody, expectedResponseBody) {
|
var database, cache map[string]interface{}
|
||||||
t.Errorf("handler returned unexpected body: got %v want %v",
|
if decodedResponseBody[0]["message"] == "database" {
|
||||||
decodedResponseBody, expectedResponseBody)
|
database = decodedResponseBody[0]
|
||||||
|
cache = decodedResponseBody[1]
|
||||||
|
} else {
|
||||||
|
database = decodedResponseBody[1]
|
||||||
|
cache = decodedResponseBody[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expectedResponseBody[0], database)
|
||||||
|
assert.Equal(t, expectedResponseBody[1], cache)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -498,6 +498,7 @@ func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *A
|
|||||||
|
|
||||||
// InsertFilterChain adds a FilterFunc built by filterChain.
|
// InsertFilterChain adds a FilterFunc built by filterChain.
|
||||||
// This filter will be executed before all filters.
|
// This filter will be executed before all filters.
|
||||||
|
// the filter's behavior is like stack
|
||||||
func InsertFilterChain(pattern string, filterChain FilterChain, params ...bool) *App {
|
func InsertFilterChain(pattern string, filterChain FilterChain, params ...bool) *App {
|
||||||
BeeApp.Handlers.InsertFilterChain(pattern, filterChain, params...)
|
BeeApp.Handlers.InsertFilterChain(pattern, filterChain, params...)
|
||||||
return BeeApp
|
return BeeApp
|
||||||
|
@ -33,6 +33,7 @@ type FilterFunc func(ctx *context.Context)
|
|||||||
// when a request with a matching URL arrives.
|
// when a request with a matching URL arrives.
|
||||||
type FilterRouter struct {
|
type FilterRouter struct {
|
||||||
filterFunc FilterFunc
|
filterFunc FilterFunc
|
||||||
|
next *FilterRouter
|
||||||
tree *Tree
|
tree *Tree
|
||||||
pattern string
|
pattern string
|
||||||
returnOnOutput bool
|
returnOnOutput bool
|
||||||
@ -81,6 +82,8 @@ func (f *FilterRouter) filter(ctx *context.Context, urlPath string, preFilterPar
|
|||||||
ctx.Input.SetParam(k, v)
|
ctx.Input.SetParam(k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if f.next != nil {
|
||||||
|
return f.next.filter(ctx, urlPath, preFilterParams)
|
||||||
}
|
}
|
||||||
if f.returnOnOutput && ctx.ResponseWriter.Started {
|
if f.returnOnOutput && ctx.ResponseWriter.Started {
|
||||||
return true, true
|
return true, true
|
||||||
|
@ -39,7 +39,6 @@ func TestControllerRegister_InsertFilterChain(t *testing.T) {
|
|||||||
ctx.Output.Body([]byte("hello"))
|
ctx.Output.Body([]byte("hello"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
r, _ := http.NewRequest("GET", "/chain/user", nil)
|
r, _ := http.NewRequest("GET", "/chain/user", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
@ -17,14 +17,11 @@ package opentracing
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/pkg/httplib"
|
||||||
logKit "github.com/go-kit/kit/log"
|
logKit "github.com/go-kit/kit/log"
|
||||||
opentracingKit "github.com/go-kit/kit/tracing/opentracing"
|
opentracingKit "github.com/go-kit/kit/tracing/opentracing"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/opentracing/opentracing-go/log"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/pkg/httplib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FilterChainBuilder struct {
|
type FilterChainBuilder struct {
|
||||||
@ -38,14 +35,8 @@ func (builder *FilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filt
|
|||||||
return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
|
return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
|
||||||
|
|
||||||
method := req.GetRequest().Method
|
method := req.GetRequest().Method
|
||||||
host := req.GetRequest().URL.Host
|
|
||||||
path := req.GetRequest().URL.Path
|
|
||||||
|
|
||||||
proto := req.GetRequest().Proto
|
operationName := method + "#" + req.GetRequest().URL.String()
|
||||||
|
|
||||||
scheme := req.GetRequest().URL.Scheme
|
|
||||||
|
|
||||||
operationName := host + path + "#" + method
|
|
||||||
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
|
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
@ -54,21 +45,24 @@ func (builder *FilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filt
|
|||||||
resp, err := next(spanCtx, req)
|
resp, err := next(spanCtx, req)
|
||||||
|
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
span.SetTag("status", strconv.Itoa(resp.StatusCode))
|
span.SetTag("http.status_code", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
span.SetTag("http.method", method)
|
||||||
span.SetTag("method", method)
|
span.SetTag("peer.hostname", req.GetRequest().URL.Host)
|
||||||
span.SetTag("host", host)
|
span.SetTag("http.url", req.GetRequest().URL.String())
|
||||||
span.SetTag("path", path)
|
span.SetTag("http.scheme", req.GetRequest().URL.Scheme)
|
||||||
span.SetTag("proto", proto)
|
span.SetTag("span.kind", "client")
|
||||||
span.SetTag("scheme", scheme)
|
span.SetTag("component", "beego")
|
||||||
|
|
||||||
span.LogFields(log.String("url", req.GetRequest().URL.String()))
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(log.String("error", err.Error()))
|
span.SetTag("error", true)
|
||||||
|
span.SetTag("message", err.Error())
|
||||||
|
} else if resp != nil && !(resp.StatusCode < 300 && resp.StatusCode >= 200) {
|
||||||
|
span.SetTag("error", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.SetTag("peer.address", req.GetRequest().RemoteAddr)
|
||||||
|
span.SetTag("http.proto", req.GetRequest().Proto)
|
||||||
|
|
||||||
if builder.CustomSpanFunc != nil {
|
if builder.CustomSpanFunc != nil {
|
||||||
builder.CustomSpanFunc(span, ctx, req, resp, err)
|
builder.CustomSpanFunc(span, ctx, req, resp, err)
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,13 @@ func (builder *FilterChainBuilder) report(startTime time.Time, endTime time.Time
|
|||||||
host := req.GetRequest().URL.Host
|
host := req.GetRequest().URL.Host
|
||||||
path := req.GetRequest().URL.Path
|
path := req.GetRequest().URL.Path
|
||||||
|
|
||||||
status := resp.StatusCode
|
status := -1
|
||||||
|
if resp != nil {
|
||||||
|
status = resp.StatusCode
|
||||||
|
}
|
||||||
|
|
||||||
dur := int(endTime.Sub(startTime) / time.Millisecond)
|
dur := int(endTime.Sub(startTime) / time.Millisecond)
|
||||||
|
|
||||||
|
|
||||||
builder.summaryVec.WithLabelValues(proto, scheme, method, host, path,
|
builder.summaryVec.WithLabelValues(proto, scheme, method, host, path,
|
||||||
strconv.Itoa(status), strconv.Itoa(dur), strconv.FormatBool(err == nil))
|
strconv.Itoa(status), strconv.Itoa(dur), strconv.FormatBool(err == nil))
|
||||||
}
|
}
|
||||||
|
@ -485,7 +485,12 @@ func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []s
|
|||||||
if isMulti {
|
if isMulti {
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
return res.LastInsertId()
|
|
||||||
|
lastInsertId, err:=res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
DebugLog.Println("[WARN] return LastInsertId error:", err)
|
||||||
|
}
|
||||||
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB, params ...common.KV
|
|||||||
return al, nil
|
return al, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.KV)(*alias, error){
|
func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.KV) (*alias, error) {
|
||||||
kvs := common.NewKVs(params...)
|
kvs := common.NewKVs(params...)
|
||||||
|
|
||||||
var stmtCache *lru.Cache
|
var stmtCache *lru.Cache
|
||||||
@ -430,7 +430,6 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...common
|
|||||||
al *alias
|
al *alias
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
db, err = sql.Open(driverName, dataSource)
|
db, err = sql.Open(driverName, dataSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
|
err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
|
||||||
|
@ -76,7 +76,6 @@ func TestRegisterDataBase_MaxStmtCacheSize841(t *testing.T) {
|
|||||||
assert.Equal(t, al.DB.stmtDecoratorsLimit, 841)
|
assert.Equal(t, al.DB.stmtDecoratorsLimit, 841)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestDBCache(t *testing.T) {
|
func TestDBCache(t *testing.T) {
|
||||||
dataBaseCache.add("test1", &alias{})
|
dataBaseCache.add("test1", &alias{})
|
||||||
dataBaseCache.add("default", &alias{})
|
dataBaseCache.add("default", &alias{})
|
||||||
|
@ -150,7 +150,12 @@ func (d *dbBaseOracle) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, nam
|
|||||||
if isMulti {
|
if isMulti {
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
return res.LastInsertId()
|
|
||||||
|
lastInsertId, err := res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
DebugLog.Println("[WARN] return LastInsertId error:", err)
|
||||||
|
}
|
||||||
|
return lastInsertId, nil
|
||||||
}
|
}
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
var _ Ormer = new(DoNothingOrm)
|
var _ Ormer = new(DoNothingOrm)
|
||||||
|
|
||||||
type DoNothingOrm struct {
|
type DoNothingOrm struct {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DoNothingOrm) Read(md interface{}, cols ...string) error {
|
func (d *DoNothingOrm) Read(md interface{}, cols ...string) error {
|
||||||
@ -149,19 +150,19 @@ func (d *DoNothingOrm) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOpti
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DoNothingOrm) DoTx(task func(txOrm TxOrmer) error) error {
|
func (d *DoNothingOrm) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DoNothingOrm) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error {
|
func (d *DoNothingOrm) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DoNothingOrm) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (d *DoNothingOrm) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DoNothingOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (d *DoNothingOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
// don't forget to call next(...) inside your Filter
|
// don't forget to call next(...) inside your Filter
|
||||||
type FilterChain func(next Filter) Filter
|
type FilterChain func(next Filter) Filter
|
||||||
|
|
||||||
// Filter's behavior is a little big strang.
|
// Filter's behavior is a little big strange.
|
||||||
// it's only be called when users call methods of Ormer
|
// it's only be called when users call methods of Ormer
|
||||||
type Filter func(ctx context.Context, inv *Invocation)
|
type Filter func(ctx context.Context, inv *Invocation)
|
||||||
|
|
||||||
@ -31,6 +31,6 @@ var globalFilterChains = make([]FilterChain, 0, 4)
|
|||||||
// AddGlobalFilterChain adds a new FilterChain
|
// AddGlobalFilterChain adds a new FilterChain
|
||||||
// All orm instances built after this invocation will use this filterChain,
|
// All orm instances built after this invocation will use this filterChain,
|
||||||
// but instances built before this invocation will not be affected
|
// but instances built before this invocation will not be affected
|
||||||
func AddGlobalFilterChain(filterChain FilterChain) {
|
func AddGlobalFilterChain(filterChain ...FilterChain) {
|
||||||
globalFilterChains = append(globalFilterChains, filterChain)
|
globalFilterChains = append(globalFilterChains, filterChain...)
|
||||||
}
|
}
|
@ -37,7 +37,6 @@ func TestDefaultValueFilterChainBuilder_FilterChain(t *testing.T) {
|
|||||||
entity = &DefaultValueTestEntity{}
|
entity = &DefaultValueTestEntity{}
|
||||||
orm.RegisterModel(entity)
|
orm.RegisterModel(entity)
|
||||||
|
|
||||||
|
|
||||||
_, _ = o.InsertOrUpdate(entity)
|
_, _ = o.InsertOrUpdate(entity)
|
||||||
assert.Equal(t, 12, entity.Age)
|
assert.Equal(t, 12, entity.Age)
|
||||||
assert.Equal(t, 13, entity.AgeInOldStyle)
|
assert.Equal(t, 13, entity.AgeInOldStyle)
|
||||||
@ -66,7 +65,7 @@ type defaultValueTestOrm struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DefaultValueTestEntity struct {
|
type DefaultValueTestEntity struct {
|
||||||
Id int`orm:pk`
|
Id int
|
||||||
Age int `default:"12"`
|
Age int `default:"12"`
|
||||||
AgeInOldStyle int `orm:"default(13);bee()"`
|
AgeInOldStyle int `orm:"default(13);bee()"`
|
||||||
AgeIgnore int
|
AgeIgnore int
|
||||||
|
@ -16,6 +16,7 @@ package opentracing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
|
|
||||||
@ -27,6 +28,8 @@ import (
|
|||||||
// for example:
|
// for example:
|
||||||
// if we want to trace QuerySetter
|
// if we want to trace QuerySetter
|
||||||
// actually we trace invoking "QueryTable" and "QueryTableWithCtx"
|
// actually we trace invoking "QueryTable" and "QueryTableWithCtx"
|
||||||
|
// the method Begin*, Commit and Rollback are ignored.
|
||||||
|
// When use using those methods, it means that they want to manager their transaction manually, so we won't handle them.
|
||||||
type FilterChainBuilder struct {
|
type FilterChainBuilder struct {
|
||||||
// CustomSpanFunc users are able to custom their span
|
// CustomSpanFunc users are able to custom their span
|
||||||
CustomSpanFunc func(span opentracing.Span, ctx context.Context, inv *orm.Invocation)
|
CustomSpanFunc func(span opentracing.Span, ctx context.Context, inv *orm.Invocation)
|
||||||
@ -35,25 +38,34 @@ type FilterChainBuilder struct {
|
|||||||
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
|
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
|
||||||
return func(ctx context.Context, inv *orm.Invocation) {
|
return func(ctx context.Context, inv *orm.Invocation) {
|
||||||
operationName := builder.operationName(ctx, inv)
|
operationName := builder.operationName(ctx, inv)
|
||||||
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
|
if strings.HasPrefix(inv.Method, "Begin") || inv.Method == "Commit" || inv.Method == "Rollback" {
|
||||||
defer span.Finish()
|
next(ctx, inv)
|
||||||
|
return
|
||||||
next(spanCtx, inv)
|
|
||||||
span.SetTag("Method", inv.Method)
|
|
||||||
span.SetTag("Table", inv.GetTableName())
|
|
||||||
span.SetTag("InsideTx", inv.InsideTx)
|
|
||||||
span.SetTag("TxName", spanCtx.Value(orm.TxNameKey))
|
|
||||||
|
|
||||||
if builder.CustomSpanFunc != nil {
|
|
||||||
builder.CustomSpanFunc(span, spanCtx, inv)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
|
||||||
|
defer span.Finish()
|
||||||
|
next(spanCtx, inv)
|
||||||
|
builder.buildSpan(span, spanCtx, inv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (builder *FilterChainBuilder) buildSpan(span opentracing.Span, ctx context.Context, inv *orm.Invocation) {
|
||||||
|
span.SetTag("orm.method", inv.Method)
|
||||||
|
span.SetTag("orm.table", inv.GetTableName())
|
||||||
|
span.SetTag("orm.insideTx", inv.InsideTx)
|
||||||
|
span.SetTag("orm.txName", ctx.Value(orm.TxNameKey))
|
||||||
|
span.SetTag("span.kind", "client")
|
||||||
|
span.SetTag("component", "beego")
|
||||||
|
|
||||||
|
if builder.CustomSpanFunc != nil {
|
||||||
|
builder.CustomSpanFunc(span, ctx, inv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (builder *FilterChainBuilder) operationName(ctx context.Context, inv *orm.Invocation) string {
|
func (builder *FilterChainBuilder) operationName(ctx context.Context, inv *orm.Invocation) string {
|
||||||
if n, ok := ctx.Value(orm.TxNameKey).(string); ok {
|
if n, ok := ctx.Value(orm.TxNameKey).(string); ok {
|
||||||
return inv.Method + "#" + n
|
return inv.Method + "#tx(" + n + ")"
|
||||||
}
|
}
|
||||||
return inv.Method + "#" + inv.GetTableName()
|
return inv.Method + "#" + inv.GetTableName()
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const TxNameKey = "TxName"
|
const (
|
||||||
|
TxNameKey = "TxName"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Ormer = new(filterOrmDecorator)
|
||||||
|
var _ TxOrmer = new(filterOrmDecorator)
|
||||||
|
|
||||||
type filterOrmDecorator struct {
|
type filterOrmDecorator struct {
|
||||||
ormer
|
ormer
|
||||||
@ -41,7 +46,7 @@ func NewFilterOrmDecorator(delegate Ormer, filterChains ...FilterChain) Ormer {
|
|||||||
ormer: delegate,
|
ormer: delegate,
|
||||||
TxBeginner: delegate,
|
TxBeginner: delegate,
|
||||||
root: func(ctx context.Context, inv *Invocation) {
|
root: func(ctx context.Context, inv *Invocation) {
|
||||||
inv.execute()
|
inv.execute(ctx)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +64,7 @@ func NewFilterTxOrmDecorator(delegate TxOrmer, root Filter, txName string) TxOrm
|
|||||||
root: root,
|
root: root,
|
||||||
insideTx: true,
|
insideTx: true,
|
||||||
txStartTime: time.Now(),
|
txStartTime: time.Now(),
|
||||||
txName: txName,
|
txName: txName,
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
@ -77,8 +82,8 @@ func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, co
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
err = f.ormer.ReadWithCtx(ctx, md, cols...)
|
err = f.ormer.ReadWithCtx(c, md, cols...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -99,8 +104,8 @@ func (f *filterOrmDecorator) ReadForUpdateWithCtx(ctx context.Context, md interf
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
err = f.ormer.ReadForUpdateWithCtx(ctx, md, cols...)
|
err = f.ormer.ReadForUpdateWithCtx(c, md, cols...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -126,8 +131,8 @@ func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interfa
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
ok, res, err = f.ormer.ReadOrCreateWithCtx(ctx, md, col1, cols...)
|
ok, res, err = f.ormer.ReadOrCreateWithCtx(c, md, col1, cols...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -152,8 +157,8 @@ func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interfac
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.LoadRelatedWithCtx(ctx, md, name, args...)
|
res, err = f.ormer.LoadRelatedWithCtx(c, md, name, args...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -177,8 +182,8 @@ func (f *filterOrmDecorator) QueryM2MWithCtx(ctx context.Context, md interface{}
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res = f.ormer.QueryM2MWithCtx(ctx, md, name)
|
res = f.ormer.QueryM2MWithCtx(c, md, name)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -191,10 +196,10 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS
|
|||||||
|
|
||||||
func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter {
|
func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter {
|
||||||
var (
|
var (
|
||||||
res QuerySeter
|
res QuerySeter
|
||||||
name string
|
name string
|
||||||
md interface{}
|
md interface{}
|
||||||
mi *modelInfo
|
mi *modelInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
if table, ok := ptrStructOrTableName.(string); ok {
|
if table, ok := ptrStructOrTableName.(string); ok {
|
||||||
@ -213,10 +218,10 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
|
|||||||
Args: []interface{}{ptrStructOrTableName},
|
Args: []interface{}{ptrStructOrTableName},
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
Md: md,
|
Md: md,
|
||||||
mi: mi,
|
mi: mi,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res = f.ormer.QueryTableWithCtx(ctx, ptrStructOrTableName)
|
res = f.ormer.QueryTableWithCtx(c, ptrStructOrTableName)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -231,7 +236,7 @@ func (f *filterOrmDecorator) DBStats() *sql.DBStats {
|
|||||||
Method: "DBStats",
|
Method: "DBStats",
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res = f.ormer.DBStats()
|
res = f.ormer.DBStats()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -256,8 +261,8 @@ func (f *filterOrmDecorator) InsertWithCtx(ctx context.Context, md interface{})
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.InsertWithCtx(ctx, md)
|
res, err = f.ormer.InsertWithCtx(c, md)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -281,8 +286,8 @@ func (f *filterOrmDecorator) InsertOrUpdateWithCtx(ctx context.Context, md inter
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.InsertOrUpdateWithCtx(ctx, md, colConflitAndArgs...)
|
res, err = f.ormer.InsertOrUpdateWithCtx(c, md, colConflitAndArgs...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -317,8 +322,8 @@ func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, m
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.InsertMultiWithCtx(ctx, bulk, mds)
|
res, err = f.ormer.InsertMultiWithCtx(c, bulk, mds)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -342,8 +347,8 @@ func (f *filterOrmDecorator) UpdateWithCtx(ctx context.Context, md interface{},
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.UpdateWithCtx(ctx, md, cols...)
|
res, err = f.ormer.UpdateWithCtx(c, md, cols...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -367,8 +372,8 @@ func (f *filterOrmDecorator) DeleteWithCtx(ctx context.Context, md interface{},
|
|||||||
mi: mi,
|
mi: mi,
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.ormer.DeleteWithCtx(ctx, md, cols...)
|
res, err = f.ormer.DeleteWithCtx(c, md, cols...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -388,8 +393,8 @@ func (f *filterOrmDecorator) RawWithCtx(ctx context.Context, query string, args
|
|||||||
Args: []interface{}{query, args},
|
Args: []interface{}{query, args},
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res = f.ormer.RawWithCtx(ctx, query, args...)
|
res = f.ormer.RawWithCtx(c, query, args...)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -404,7 +409,7 @@ func (f *filterOrmDecorator) Driver() Driver {
|
|||||||
Method: "Driver",
|
Method: "Driver",
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res = f.ormer.Driver()
|
res = f.ormer.Driver()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -434,28 +439,28 @@ func (f *filterOrmDecorator) BeginWithCtxAndOpts(ctx context.Context, opts *sql.
|
|||||||
Args: []interface{}{opts},
|
Args: []interface{}{opts},
|
||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
res, err = f.TxBeginner.BeginWithCtxAndOpts(ctx, opts)
|
res, err = f.TxBeginner.BeginWithCtxAndOpts(c, opts)
|
||||||
res = NewFilterTxOrmDecorator(res, f.root, getTxNameFromCtx(ctx))
|
res = NewFilterTxOrmDecorator(res, f.root, getTxNameFromCtx(c))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterOrmDecorator) DoTx(task func(txOrm TxOrmer) error) error {
|
func (f *filterOrmDecorator) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return f.DoTxWithCtxAndOpts(context.Background(), nil, task)
|
return f.DoTxWithCtxAndOpts(context.Background(), nil, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterOrmDecorator) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error {
|
func (f *filterOrmDecorator) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return f.DoTxWithCtxAndOpts(ctx, nil, task)
|
return f.DoTxWithCtxAndOpts(ctx, nil, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterOrmDecorator) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (f *filterOrmDecorator) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return f.DoTxWithCtxAndOpts(context.Background(), opts, task)
|
return f.DoTxWithCtxAndOpts(context.Background(), opts, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
@ -466,8 +471,8 @@ func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.T
|
|||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
TxName: getTxNameFromCtx(ctx),
|
TxName: getTxNameFromCtx(ctx),
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
err = f.TxBeginner.DoTxWithCtxAndOpts(ctx, opts, task)
|
err = doTxTemplate(f, c, opts, task)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
f.root(ctx, inv)
|
f.root(ctx, inv)
|
||||||
@ -484,7 +489,7 @@ func (f *filterOrmDecorator) Commit() error {
|
|||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
TxName: f.txName,
|
TxName: f.txName,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
err = f.TxCommitter.Commit()
|
err = f.TxCommitter.Commit()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -502,7 +507,7 @@ func (f *filterOrmDecorator) Rollback() error {
|
|||||||
InsideTx: f.insideTx,
|
InsideTx: f.insideTx,
|
||||||
TxStartTime: f.txStartTime,
|
TxStartTime: f.txStartTime,
|
||||||
TxName: f.txName,
|
TxName: f.txName,
|
||||||
f: func() {
|
f: func(c context.Context) {
|
||||||
err = f.TxCommitter.Rollback()
|
err = f.TxCommitter.Rollback()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -517,4 +522,3 @@ func getTxNameFromCtx(ctx context.Context) string {
|
|||||||
}
|
}
|
||||||
return txName
|
return txName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,49 +131,49 @@ func TestFilterOrmDecorator_DoTx(t *testing.T) {
|
|||||||
o := &filterMockOrm{}
|
o := &filterMockOrm{}
|
||||||
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
|
od := NewFilterOrmDecorator(o, func(next Filter) Filter {
|
||||||
return func(ctx context.Context, inv *Invocation) {
|
return func(ctx context.Context, inv *Invocation) {
|
||||||
assert.Equal(t, "DoTxWithCtxAndOpts", inv.Method)
|
if inv.Method == "DoTxWithCtxAndOpts" {
|
||||||
assert.Equal(t, 2, len(inv.Args))
|
assert.Equal(t, 2, len(inv.Args))
|
||||||
assert.Equal(t, "", inv.GetTableName())
|
assert.Equal(t, "", inv.GetTableName())
|
||||||
assert.False(t, inv.InsideTx)
|
assert.False(t, inv.InsideTx)
|
||||||
|
}
|
||||||
|
|
||||||
next(ctx, inv)
|
next(ctx, inv)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
err := od.DoTx(func(txOrm TxOrmer) error {
|
err := od.DoTx(func(c context.Context, txOrm TxOrmer) error {
|
||||||
return errors.New("tx error")
|
return nil
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, "tx error", err.Error())
|
|
||||||
|
|
||||||
err = od.DoTxWithCtx(context.Background(), func(txOrm TxOrmer) error {
|
err = od.DoTxWithCtx(context.Background(), func(c context.Context, txOrm TxOrmer) error {
|
||||||
return errors.New("tx ctx error")
|
return nil
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, "tx ctx error", err.Error())
|
|
||||||
|
|
||||||
err = od.DoTxWithOpts(nil, func(txOrm TxOrmer) error {
|
err = od.DoTxWithOpts(nil, func(c context.Context, txOrm TxOrmer) error {
|
||||||
return errors.New("tx opts error")
|
return nil
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, "tx opts error", err.Error())
|
|
||||||
|
|
||||||
od = NewFilterOrmDecorator(o, func(next Filter) Filter {
|
od = NewFilterOrmDecorator(o, func(next Filter) Filter {
|
||||||
return func(ctx context.Context, inv *Invocation) {
|
return func(ctx context.Context, inv *Invocation) {
|
||||||
assert.Equal(t, "DoTxWithCtxAndOpts", inv.Method)
|
if inv.Method == "DoTxWithCtxAndOpts" {
|
||||||
assert.Equal(t, 2, len(inv.Args))
|
assert.Equal(t, 2, len(inv.Args))
|
||||||
assert.Equal(t, "", inv.GetTableName())
|
assert.Equal(t, "", inv.GetTableName())
|
||||||
assert.Equal(t, "do tx name", inv.TxName)
|
assert.Equal(t, "do tx name", inv.TxName)
|
||||||
assert.False(t, inv.InsideTx)
|
assert.False(t, inv.InsideTx)
|
||||||
|
}
|
||||||
next(ctx, inv)
|
next(ctx, inv)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx := context.WithValue(context.Background(), TxNameKey, "do tx name")
|
ctx := context.WithValue(context.Background(), TxNameKey, "do tx name")
|
||||||
err = od.DoTxWithCtxAndOpts(ctx, nil, func(txOrm TxOrmer) error {
|
err = od.DoTxWithCtxAndOpts(ctx, nil, func(c context.Context, txOrm TxOrmer) error {
|
||||||
return errors.New("tx ctx opts error")
|
return nil
|
||||||
})
|
})
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
assert.Equal(t, "tx ctx opts error", err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterOrmDecorator_Driver(t *testing.T) {
|
func TestFilterOrmDecorator_Driver(t *testing.T) {
|
||||||
@ -348,6 +348,8 @@ func TestFilterOrmDecorator_ReadOrCreate(t *testing.T) {
|
|||||||
assert.Equal(t, int64(13), i)
|
assert.Equal(t, int64(13), i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ Ormer = new(filterMockOrm)
|
||||||
|
|
||||||
// filterMockOrm is only used in this test file
|
// filterMockOrm is only used in this test file
|
||||||
type filterMockOrm struct {
|
type filterMockOrm struct {
|
||||||
DoNothingOrm
|
DoNothingOrm
|
||||||
@ -377,8 +379,8 @@ func (f *filterMockOrm) InsertWithCtx(ctx context.Context, md interface{}) (int6
|
|||||||
return 100, errors.New("insert error")
|
return 100, errors.New("insert error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterMockOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (f *filterMockOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(c context.Context, txOrm TxOrmer) error) error {
|
||||||
return task(nil)
|
return task(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *filterMockOrm) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
|
func (f *filterMockOrm) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
|
||||||
|
@ -28,4 +28,5 @@ func TestAddGlobalFilterChain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
assert.Equal(t, 1, len(globalFilterChains))
|
assert.Equal(t, 1, len(globalFilterChains))
|
||||||
|
globalFilterChains = nil
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package orm
|
package orm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,29 +23,29 @@ import (
|
|||||||
type Invocation struct {
|
type Invocation struct {
|
||||||
Method string
|
Method string
|
||||||
// Md may be nil in some cases. It depends on method
|
// Md may be nil in some cases. It depends on method
|
||||||
Md interface{}
|
Md interface{}
|
||||||
// the args are all arguments except context.Context
|
// the args are all arguments except context.Context
|
||||||
Args []interface{}
|
Args []interface{}
|
||||||
|
|
||||||
mi *modelInfo
|
mi *modelInfo
|
||||||
// f is the Orm operation
|
// f is the Orm operation
|
||||||
f func()
|
f func(ctx context.Context)
|
||||||
|
|
||||||
// insideTx indicates whether this is inside a transaction
|
// insideTx indicates whether this is inside a transaction
|
||||||
InsideTx bool
|
InsideTx bool
|
||||||
TxStartTime time.Time
|
TxStartTime time.Time
|
||||||
TxName string
|
TxName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv *Invocation) GetTableName() string {
|
func (inv *Invocation) GetTableName() string {
|
||||||
if inv.mi != nil{
|
if inv.mi != nil {
|
||||||
return inv.mi.table
|
return inv.mi.table
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv *Invocation) execute() {
|
func (inv *Invocation) execute(ctx context.Context) {
|
||||||
inv.f()
|
inv.f(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPkFieldName return the primary key of this table
|
// GetPkFieldName return the primary key of this table
|
||||||
|
@ -28,7 +28,6 @@ import (
|
|||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
// As tidb can't use go get, so disable the tidb testing now
|
// As tidb can't use go get, so disable the tidb testing now
|
||||||
// _ "github.com/pingcap/tidb"
|
// _ "github.com/pingcap/tidb"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A slice string field.
|
// A slice string field.
|
||||||
@ -422,6 +421,11 @@ type PtrPk struct {
|
|||||||
Positive bool
|
Positive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StrPk struct {
|
||||||
|
Id string `orm:"column(id);size(64);pk"`
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
var DBARGS = struct {
|
var DBARGS = struct {
|
||||||
Driver string
|
Driver string
|
||||||
Source string
|
Source string
|
||||||
|
@ -528,19 +528,24 @@ func (o *orm) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxO
|
|||||||
return taskTxOrm, nil
|
return taskTxOrm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orm) DoTx(task func(txOrm TxOrmer) error) error {
|
func (o *orm) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return o.DoTxWithCtx(context.Background(), task)
|
return o.DoTxWithCtx(context.Background(), task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orm) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error {
|
func (o *orm) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return o.DoTxWithCtxAndOpts(ctx, nil, task)
|
return o.DoTxWithCtxAndOpts(ctx, nil, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orm) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (o *orm) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
return o.DoTxWithCtxAndOpts(context.Background(), opts, task)
|
return o.DoTxWithCtxAndOpts(context.Background(), opts, task)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error {
|
func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
|
return doTxTemplate(o, ctx, opts, task)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doTxTemplate(o TxBeginner, ctx context.Context, opts *sql.TxOptions,
|
||||||
|
task func(ctx context.Context, txOrm TxOrmer) error) error {
|
||||||
_txOrm, err := o.BeginWithCtxAndOpts(ctx, opts)
|
_txOrm, err := o.BeginWithCtxAndOpts(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -559,9 +564,8 @@ func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var taskTxOrm = _txOrm
|
var taskTxOrm = _txOrm
|
||||||
err = task(taskTxOrm)
|
err = task(ctx, taskTxOrm)
|
||||||
panicked = false
|
panicked = false
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -588,18 +592,11 @@ func NewOrm() Ormer {
|
|||||||
|
|
||||||
// NewOrmUsingDB create new orm with the name
|
// NewOrmUsingDB create new orm with the name
|
||||||
func NewOrmUsingDB(aliasName string) Ormer {
|
func NewOrmUsingDB(aliasName string) Ormer {
|
||||||
o := new(orm)
|
|
||||||
if al, ok := dataBaseCache.get(aliasName); ok {
|
if al, ok := dataBaseCache.get(aliasName); ok {
|
||||||
o.alias = al
|
return newDBWithAlias(al)
|
||||||
if Debug {
|
|
||||||
o.db = newDbQueryLog(al, al.DB)
|
|
||||||
} else {
|
|
||||||
o.db = al.DB
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf("<Ormer.Using> unknown db alias name `%s`", aliasName))
|
panic(fmt.Errorf("<Ormer.Using> unknown db alias name `%s`", aliasName))
|
||||||
}
|
}
|
||||||
return o
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOrmWithDB create a new ormer object with specify *sql.DB for query
|
// NewOrmWithDB create a new ormer object with specify *sql.DB for query
|
||||||
@ -609,14 +606,21 @@ func NewOrmWithDB(driverName, aliasName string, db *sql.DB, params ...common.KV)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newDBWithAlias(al), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDBWithAlias(al *alias) Ormer {
|
||||||
o := new(orm)
|
o := new(orm)
|
||||||
o.alias = al
|
o.alias = al
|
||||||
|
|
||||||
if Debug {
|
if Debug {
|
||||||
o.db = newDbQueryLog(o.alias, db)
|
o.db = newDbQueryLog(al, al.DB)
|
||||||
} else {
|
} else {
|
||||||
o.db = db
|
o.db = al.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
return o, nil
|
if len(globalFilterChains) > 0 {
|
||||||
|
return NewFilterOrmDecorator(o, globalFilterChains...)
|
||||||
|
}
|
||||||
|
return o
|
||||||
}
|
}
|
||||||
|
@ -202,6 +202,7 @@ func TestSyncDb(t *testing.T) {
|
|||||||
RegisterModel(new(UintPk))
|
RegisterModel(new(UintPk))
|
||||||
RegisterModel(new(PtrPk))
|
RegisterModel(new(PtrPk))
|
||||||
RegisterModel(new(Index))
|
RegisterModel(new(Index))
|
||||||
|
RegisterModel(new(StrPk))
|
||||||
|
|
||||||
err := RunSyncdb("default", true, Debug)
|
err := RunSyncdb("default", true, Debug)
|
||||||
throwFail(t, err)
|
throwFail(t, err)
|
||||||
@ -227,6 +228,7 @@ func TestRegisterModels(t *testing.T) {
|
|||||||
RegisterModel(new(UintPk))
|
RegisterModel(new(UintPk))
|
||||||
RegisterModel(new(PtrPk))
|
RegisterModel(new(PtrPk))
|
||||||
RegisterModel(new(Index))
|
RegisterModel(new(Index))
|
||||||
|
RegisterModel(new(StrPk))
|
||||||
|
|
||||||
BootStrap()
|
BootStrap()
|
||||||
|
|
||||||
@ -2524,4 +2526,21 @@ func TestInsertOrUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStrPkInsert(t *testing.T) {
|
||||||
|
RegisterModel(new(StrPk))
|
||||||
|
value := `StrPkValues(*56`
|
||||||
|
strPk := &StrPk{
|
||||||
|
Id: "1",
|
||||||
|
Value: value,
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
_, err = dORM.Insert(strPk)
|
||||||
|
throwFailNow(t, AssertIs(err, nil))
|
||||||
|
|
||||||
|
var vForTesting StrPk
|
||||||
|
err = dORM.QueryTable(new(StrPk)).Filter(`id`, `1`).One(&vForTesting)
|
||||||
|
throwFailNow(t, AssertIs(err, nil))
|
||||||
|
throwFailNow(t, AssertIs(vForTesting.Value, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -96,10 +96,10 @@ type TxBeginner interface {
|
|||||||
BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error)
|
BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error)
|
||||||
|
|
||||||
//closure control transaction
|
//closure control transaction
|
||||||
DoTx(task func(txOrm TxOrmer) error) error
|
DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error
|
||||||
DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error
|
DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error
|
||||||
DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error
|
DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
|
||||||
DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error
|
DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type TxCommitter interface {
|
type TxCommitter interface {
|
||||||
|
@ -468,12 +468,13 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter
|
|||||||
// // do something
|
// // do something
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, params...bool) {
|
func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, params ...bool) {
|
||||||
root := p.chainRoot
|
root := p.chainRoot
|
||||||
filterFunc := chain(root.filterFunc)
|
filterFunc := chain(root.filterFunc)
|
||||||
p.chainRoot = newFilterRouter(pattern, BConfig.RouterCaseSensitive, filterFunc, params...)
|
p.chainRoot = newFilterRouter(pattern, BConfig.RouterCaseSensitive, filterFunc, params...)
|
||||||
}
|
p.chainRoot.next = root
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// add Filter into
|
// add Filter into
|
||||||
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) {
|
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) {
|
||||||
|
@ -41,7 +41,7 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/pkg/session"
|
"github.com/astaxie/beego/pkg/session"
|
||||||
|
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/go-redis/redis/v7"
|
||||||
)
|
)
|
||||||
|
|
||||||
var redispder = &Provider{}
|
var redispder = &Provider{}
|
||||||
@ -51,7 +51,7 @@ var MaxPoolSize = 100
|
|||||||
|
|
||||||
// SessionStore redis session store
|
// SessionStore redis session store
|
||||||
type SessionStore struct {
|
type SessionStore struct {
|
||||||
p *redis.Pool
|
p *redis.Client
|
||||||
sid string
|
sid string
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
values map[interface{}]interface{}
|
values map[interface{}]interface{}
|
||||||
@ -103,19 +103,21 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c := rs.p.Get()
|
c := rs.p
|
||||||
defer c.Close()
|
c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second)
|
||||||
c.Do("SETEX", rs.sid, rs.maxlifetime, string(b))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider redis session provider
|
// Provider redis session provider
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
maxlifetime int64
|
maxlifetime int64
|
||||||
savePath string
|
savePath string
|
||||||
poolsize int
|
poolsize int
|
||||||
password string
|
password string
|
||||||
dbNum int
|
dbNum int
|
||||||
poollist *redis.Pool
|
idleTimeout time.Duration
|
||||||
|
idleCheckFrequency time.Duration
|
||||||
|
maxRetries int
|
||||||
|
poollist *redis.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionInit init redis session
|
// SessionInit init redis session
|
||||||
@ -150,52 +152,44 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
} else {
|
} else {
|
||||||
rp.dbNum = 0
|
rp.dbNum = 0
|
||||||
}
|
}
|
||||||
var idleTimeout time.Duration = 0
|
|
||||||
if len(configs) > 4 {
|
if len(configs) > 4 {
|
||||||
timeout, err := strconv.Atoi(configs[4])
|
timeout, err := strconv.Atoi(configs[4])
|
||||||
if err == nil && timeout > 0 {
|
if err == nil && timeout > 0 {
|
||||||
idleTimeout = time.Duration(timeout) * time.Second
|
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rp.poollist = &redis.Pool{
|
if len(configs) > 5 {
|
||||||
Dial: func() (redis.Conn, error) {
|
checkFrequency, err := strconv.Atoi(configs[5])
|
||||||
c, err := redis.Dial("tcp", rp.savePath)
|
if err == nil && checkFrequency > 0 {
|
||||||
if err != nil {
|
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||||
return nil, err
|
}
|
||||||
}
|
}
|
||||||
if rp.password != "" {
|
if len(configs) > 6 {
|
||||||
if _, err = c.Do("AUTH", rp.password); err != nil {
|
retries, err := strconv.Atoi(configs[6])
|
||||||
c.Close()
|
if err == nil && retries > 0 {
|
||||||
return nil, err
|
rp.maxRetries = retries
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// some redis proxy such as twemproxy is not support select command
|
|
||||||
if rp.dbNum > 0 {
|
|
||||||
_, err = c.Do("SELECT", rp.dbNum)
|
|
||||||
if err != nil {
|
|
||||||
c.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c, err
|
|
||||||
},
|
|
||||||
MaxIdle: rp.poolsize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rp.poollist.IdleTimeout = idleTimeout
|
rp.poollist = redis.NewClient(&redis.Options{
|
||||||
|
Addr: rp.savePath,
|
||||||
|
Password: rp.password,
|
||||||
|
PoolSize: rp.poolsize,
|
||||||
|
DB: rp.dbNum,
|
||||||
|
IdleTimeout: rp.idleTimeout,
|
||||||
|
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||||
|
MaxRetries: rp.maxRetries,
|
||||||
|
})
|
||||||
|
|
||||||
return rp.poollist.Get().Err()
|
return rp.poollist.Ping().Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionRead read redis session by sid
|
// SessionRead read redis session by sid
|
||||||
func (rp *Provider) SessionRead(sid string) (session.Store, error) {
|
func (rp *Provider) SessionRead(sid string) (session.Store, error) {
|
||||||
c := rp.poollist.Get()
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
var kv map[interface{}]interface{}
|
var kv map[interface{}]interface{}
|
||||||
|
|
||||||
kvs, err := redis.String(c.Do("GET", sid))
|
kvs, err := rp.poollist.Get(sid).Result()
|
||||||
if err != nil && err != redis.ErrNil {
|
if err != nil && err != redis.Nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(kvs) == 0 {
|
if len(kvs) == 0 {
|
||||||
@ -212,10 +206,9 @@ func (rp *Provider) SessionRead(sid string) (session.Store, error) {
|
|||||||
|
|
||||||
// SessionExist check redis session exist by sid
|
// SessionExist check redis session exist by sid
|
||||||
func (rp *Provider) SessionExist(sid string) (bool, error) {
|
func (rp *Provider) SessionExist(sid string) (bool, error) {
|
||||||
c := rp.poollist.Get()
|
c := rp.poollist
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
if existed, err := redis.Int(c.Do("EXISTS", sid)); err != nil || existed == 0 {
|
if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -223,27 +216,24 @@ func (rp *Provider) SessionExist(sid string) (bool, error) {
|
|||||||
|
|
||||||
// SessionRegenerate generate new sid for redis session
|
// SessionRegenerate generate new sid for redis session
|
||||||
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
||||||
c := rp.poollist.Get()
|
c := rp.poollist
|
||||||
defer c.Close()
|
if existed, _ := c.Exists(oldsid).Result(); existed == 0 {
|
||||||
|
|
||||||
if existed, _ := redis.Int(c.Do("EXISTS", oldsid)); existed == 0 {
|
|
||||||
// oldsid doesn't exists, set the new sid directly
|
// oldsid doesn't exists, set the new sid directly
|
||||||
// ignore error here, since if it return error
|
// ignore error here, since if it return error
|
||||||
// the existed value will be 0
|
// the existed value will be 0
|
||||||
c.Do("SET", sid, "", "EX", rp.maxlifetime)
|
c.Do(c.Context(), "SET", sid, "", "EX", rp.maxlifetime)
|
||||||
} else {
|
} else {
|
||||||
c.Do("RENAME", oldsid, sid)
|
c.Rename(oldsid, sid)
|
||||||
c.Do("EXPIRE", sid, rp.maxlifetime)
|
c.Expire(sid, time.Duration(rp.maxlifetime) * time.Second)
|
||||||
}
|
}
|
||||||
return rp.SessionRead(sid)
|
return rp.SessionRead(sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionDestroy delete redis session by id
|
// SessionDestroy delete redis session by id
|
||||||
func (rp *Provider) SessionDestroy(sid string) error {
|
func (rp *Provider) SessionDestroy(sid string) error {
|
||||||
c := rp.poollist.Get()
|
c := rp.poollist
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
c.Do("DEL", sid)
|
c.Del(sid)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
88
pkg/session/redis/sess_redis_test.go
Normal file
88
pkg/session/redis/sess_redis_test.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/pkg/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRedis(t *testing.T) {
|
||||||
|
sessionConfig := &session.ManagerConfig{
|
||||||
|
CookieName: "gosessionid",
|
||||||
|
EnableSetCookie: true,
|
||||||
|
Gclifetime: 3600,
|
||||||
|
Maxlifetime: 3600,
|
||||||
|
Secure: false,
|
||||||
|
CookieLifeTime: 3600,
|
||||||
|
ProviderConfig: "127.0.0.1:6379,100,,0,30",
|
||||||
|
}
|
||||||
|
globalSession, err := session.NewManager("redis", sessionConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("could not create manager:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go globalSession.GC()
|
||||||
|
|
||||||
|
r, _ := http.NewRequest("GET", "/", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
sess, err := globalSession.SessionStart(w, r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("session start failed:", err)
|
||||||
|
}
|
||||||
|
defer sess.SessionRelease(w)
|
||||||
|
|
||||||
|
// SET AND GET
|
||||||
|
err = sess.Set("username", "astaxie")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("set username failed:", err)
|
||||||
|
}
|
||||||
|
username := sess.Get("username")
|
||||||
|
if username != "astaxie" {
|
||||||
|
t.Fatal("get username failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE
|
||||||
|
err = sess.Delete("username")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("delete username failed:", err)
|
||||||
|
}
|
||||||
|
username = sess.Get("username")
|
||||||
|
if username != nil {
|
||||||
|
t.Fatal("delete username failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FLUSH
|
||||||
|
err = sess.Set("username", "astaxie")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("set failed:", err)
|
||||||
|
}
|
||||||
|
err = sess.Set("password", "1qaz2wsx")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("set failed:", err)
|
||||||
|
}
|
||||||
|
username = sess.Get("username")
|
||||||
|
if username != "astaxie" {
|
||||||
|
t.Fatal("get username failed")
|
||||||
|
}
|
||||||
|
password := sess.Get("password")
|
||||||
|
if password != "1qaz2wsx" {
|
||||||
|
t.Fatal("get password failed")
|
||||||
|
}
|
||||||
|
err = sess.Flush()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("flush failed:", err)
|
||||||
|
}
|
||||||
|
username = sess.Get("username")
|
||||||
|
if username != nil {
|
||||||
|
t.Fatal("flush failed")
|
||||||
|
}
|
||||||
|
password = sess.Get("password")
|
||||||
|
if password != nil {
|
||||||
|
t.Fatal("flush failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
sess.SessionRelease(w)
|
||||||
|
}
|
@ -34,7 +34,7 @@ package redis_cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/pkg/session"
|
"github.com/astaxie/beego/pkg/session"
|
||||||
rediss "github.com/go-redis/redis"
|
rediss "github.com/go-redis/redis/v7"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -107,12 +107,15 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
|
|
||||||
// Provider redis_cluster session provider
|
// Provider redis_cluster session provider
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
maxlifetime int64
|
maxlifetime int64
|
||||||
savePath string
|
savePath string
|
||||||
poolsize int
|
poolsize int
|
||||||
password string
|
password string
|
||||||
dbNum int
|
dbNum int
|
||||||
poollist *rediss.ClusterClient
|
idleTimeout time.Duration
|
||||||
|
idleCheckFrequency time.Duration
|
||||||
|
maxRetries int
|
||||||
|
poollist *rediss.ClusterClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionInit init redis_cluster session
|
// SessionInit init redis_cluster session
|
||||||
@ -147,11 +150,32 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
} else {
|
} else {
|
||||||
rp.dbNum = 0
|
rp.dbNum = 0
|
||||||
}
|
}
|
||||||
|
if len(configs) > 4 {
|
||||||
|
timeout, err := strconv.Atoi(configs[4])
|
||||||
|
if err == nil && timeout > 0 {
|
||||||
|
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(configs) > 5 {
|
||||||
|
checkFrequency, err := strconv.Atoi(configs[5])
|
||||||
|
if err == nil && checkFrequency > 0 {
|
||||||
|
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(configs) > 6 {
|
||||||
|
retries, err := strconv.Atoi(configs[6])
|
||||||
|
if err == nil && retries > 0 {
|
||||||
|
rp.maxRetries = retries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
|
rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
|
||||||
Addrs: strings.Split(rp.savePath, ";"),
|
Addrs: strings.Split(rp.savePath, ";"),
|
||||||
Password: rp.password,
|
Password: rp.password,
|
||||||
PoolSize: rp.poolsize,
|
PoolSize: rp.poolsize,
|
||||||
|
IdleTimeout: rp.idleTimeout,
|
||||||
|
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||||
|
MaxRetries: rp.maxRetries,
|
||||||
})
|
})
|
||||||
return rp.poollist.Ping().Err()
|
return rp.poollist.Ping().Err()
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ package redis_sentinel
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/pkg/session"
|
"github.com/astaxie/beego/pkg/session"
|
||||||
"github.com/go-redis/redis"
|
"github.com/go-redis/redis/v7"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -107,13 +107,16 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
|
|
||||||
// Provider redis_sentinel session provider
|
// Provider redis_sentinel session provider
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
maxlifetime int64
|
maxlifetime int64
|
||||||
savePath string
|
savePath string
|
||||||
poolsize int
|
poolsize int
|
||||||
password string
|
password string
|
||||||
dbNum int
|
dbNum int
|
||||||
poollist *redis.Client
|
idleTimeout time.Duration
|
||||||
masterName string
|
idleCheckFrequency time.Duration
|
||||||
|
maxRetries int
|
||||||
|
poollist *redis.Client
|
||||||
|
masterName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionInit init redis_sentinel session
|
// SessionInit init redis_sentinel session
|
||||||
@ -157,13 +160,34 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
} else {
|
} else {
|
||||||
rp.masterName = "mymaster"
|
rp.masterName = "mymaster"
|
||||||
}
|
}
|
||||||
|
if len(configs) > 5 {
|
||||||
|
timeout, err := strconv.Atoi(configs[4])
|
||||||
|
if err == nil && timeout > 0 {
|
||||||
|
rp.idleTimeout = time.Duration(timeout) * time.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(configs) > 6 {
|
||||||
|
checkFrequency, err := strconv.Atoi(configs[5])
|
||||||
|
if err == nil && checkFrequency > 0 {
|
||||||
|
rp.idleCheckFrequency = time.Duration(checkFrequency) * time.Second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(configs) > 7 {
|
||||||
|
retries, err := strconv.Atoi(configs[6])
|
||||||
|
if err == nil && retries > 0 {
|
||||||
|
rp.maxRetries = retries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rp.poollist = redis.NewFailoverClient(&redis.FailoverOptions{
|
rp.poollist = redis.NewFailoverClient(&redis.FailoverOptions{
|
||||||
SentinelAddrs: strings.Split(rp.savePath, ";"),
|
SentinelAddrs: strings.Split(rp.savePath, ";"),
|
||||||
Password: rp.password,
|
Password: rp.password,
|
||||||
PoolSize: rp.poolsize,
|
PoolSize: rp.poolsize,
|
||||||
DB: rp.dbNum,
|
DB: rp.dbNum,
|
||||||
MasterName: rp.masterName,
|
MasterName: rp.masterName,
|
||||||
|
IdleTimeout: rp.idleTimeout,
|
||||||
|
IdleCheckFrequency: rp.idleCheckFrequency,
|
||||||
|
MaxRetries: rp.maxRetries,
|
||||||
})
|
})
|
||||||
|
|
||||||
return rp.poollist.Ping().Err()
|
return rp.poollist.Ping().Err()
|
||||||
|
@ -57,7 +57,7 @@ func TestFileProvider_SessionExist(t *testing.T) {
|
|||||||
_ = fp.SessionInit(180, sessionPath)
|
_ = fp.SessionInit(180, sessionPath)
|
||||||
|
|
||||||
exists, err := fp.SessionExist(sid)
|
exists, err := fp.SessionExist(sid)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
if exists {
|
if exists {
|
||||||
|
@ -31,7 +31,6 @@ type FilterChainBuilder struct {
|
|||||||
CustomSpanFunc func(span opentracing.Span, ctx *beegoCtx.Context)
|
CustomSpanFunc func(span opentracing.Span, ctx *beegoCtx.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc {
|
func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc {
|
||||||
return func(ctx *beegoCtx.Context) {
|
return func(ctx *beegoCtx.Context) {
|
||||||
var (
|
var (
|
||||||
@ -55,9 +54,21 @@ func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.Filt
|
|||||||
|
|
||||||
next(ctx)
|
next(ctx)
|
||||||
// if you think we need to do more things, feel free to create an issue to tell us
|
// if you think we need to do more things, feel free to create an issue to tell us
|
||||||
span.SetTag("status", ctx.Output.Status)
|
span.SetTag("http.status_code", ctx.ResponseWriter.Status)
|
||||||
span.SetTag("method", ctx.Input.Method())
|
span.SetTag("http.method", ctx.Input.Method())
|
||||||
span.SetTag("route", ctx.Input.GetData("RouterPattern"))
|
span.SetTag("peer.hostname", ctx.Request.Host)
|
||||||
|
span.SetTag("http.url", ctx.Request.URL.String())
|
||||||
|
span.SetTag("http.scheme", ctx.Request.URL.Scheme)
|
||||||
|
span.SetTag("span.kind", "server")
|
||||||
|
span.SetTag("component", "beego")
|
||||||
|
if ctx.Output.IsServerError() || ctx.Output.IsClientError() {
|
||||||
|
span.SetTag("error", true)
|
||||||
|
}
|
||||||
|
span.SetTag("peer.address", ctx.Request.RemoteAddr)
|
||||||
|
span.SetTag("http.proto", ctx.Request.Proto)
|
||||||
|
|
||||||
|
span.SetTag("beego.route", ctx.Input.GetData("RouterPattern"))
|
||||||
|
|
||||||
if builder.CustomSpanFunc != nil {
|
if builder.CustomSpanFunc != nil {
|
||||||
builder.CustomSpanFunc(span, ctx)
|
builder.CustomSpanFunc(span, ctx)
|
||||||
}
|
}
|
||||||
@ -70,7 +81,7 @@ func (builder *FilterChainBuilder) operationName(ctx *beegoCtx.Context) string {
|
|||||||
// TODO, if we support multiple servers, this need to be changed
|
// TODO, if we support multiple servers, this need to be changed
|
||||||
route, found := beego.BeeApp.Handlers.FindRouter(ctx)
|
route, found := beego.BeeApp.Handlers.FindRouter(ctx)
|
||||||
if found {
|
if found {
|
||||||
operationName = route.GetPattern()
|
operationName = ctx.Input.Method() + "#" + route.GetPattern()
|
||||||
}
|
}
|
||||||
return operationName
|
return operationName
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user