1
0
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:
Ming Deng 2020-08-13 22:00:22 +08:00
commit f73eee75ff
49 changed files with 507 additions and 280 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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)
} }

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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)
} }

View File

@ -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))
} }

View File

@ -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
} }

View File

@ -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())

View File

@ -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{})

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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...)
} }

View File

@ -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

View File

@ -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()
} }

View File

@ -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
} }

View File

@ -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) {

View File

@ -28,4 +28,5 @@ func TestAddGlobalFilterChain(t *testing.T) {
} }
}) })
assert.Equal(t, 1, len(globalFilterChains)) assert.Equal(t, 1, len(globalFilterChains))
globalFilterChains = nil
} }

View File

@ -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

View File

@ -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

View File

@ -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
} }

View File

@ -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))
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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
} }

View 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)
}

View File

@ -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()
} }

View File

@ -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()

View File

@ -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 {

View File

@ -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
} }