3
0

upd(vendor): factory database context, resputil logger

This commit is contained in:
Tit Petric 2018-07-23 17:22:10 +02:00
parent 6aaac36b51
commit 6e30992a67
6 changed files with 86 additions and 29 deletions

6
Gopkg.lock generated
View File

@ -99,7 +99,7 @@
".",
"resputil"
]
revision = "3257f6c1bf4665187bee7a68c95e6ee22afed69d"
revision = "48b00599c6785e46f875b5192c60c488f1958a13"
[[projects]]
branch = "master"
@ -122,7 +122,7 @@
"internal/timeseries",
"trace"
]
revision = "81d44fd177a98d09fe3bc40a5a78d495d3f042ea"
revision = "a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1"
[[projects]]
name = "golang.org/x/text"
@ -155,7 +155,7 @@
branch = "master"
name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"]
revision = "fedd2861243fd1a8152376292b921b394c7bef7e"
revision = "02b4e95473316948020af0b7a4f0f22c73929b0e"
[[projects]]
name = "google.golang.org/grpc"

View File

@ -1,6 +1,7 @@
package factory
import (
"context"
"fmt"
"reflect"
"strings"
@ -124,7 +125,7 @@ func (r *DatabaseFactory) Get(dbName ...string) (*DB, error) {
if err != nil {
return nil, err
}
r.instances[name] = &DB{handle, nil}
r.instances[name] = &DB{handle, context.Background(), nil}
return r.instances[name], nil
}
}
@ -144,6 +145,8 @@ func (r *DatabaseFactory) MustGet(dbName ...string) *DB {
type DB struct {
*sqlx.DB
ctx context.Context
Profiler DatabaseProfiler
}
@ -154,6 +157,14 @@ func (r *DB) Quiet() *DB {
}
}
// With will return a DB handle with a bound context (throw-away)
func (r *DB) With(ctx context.Context) *DB {
return &DB{
DB: r.DB,
ctx: ctx,
}
}
// SetFields will provide a string with SQL named bindings from a string slice
func (r *DB) SetFields(fields []string) string {
idx := 0
@ -172,11 +183,11 @@ func (r *DB) SetFields(fields []string) string {
func (r *DB) NamedExec(query string, arg interface{}) (sql.Result, error) {
if r.Profiler != nil {
ctx := DatabaseProfilerContext{}.new(query, arg)
res, err := r.DB.NamedExec(query, arg)
res, err := r.DB.NamedExecContext(r.ctx, query, arg)
r.Profiler.Post(ctx)
return res, err
}
return r.DB.NamedExec(query, arg)
return r.DB.NamedExecContext(r.ctx, query, arg)
}
// Select is a helper function that will ignore sql.ErrNoRows
@ -184,10 +195,10 @@ func (r *DB) Select(dest interface{}, query string, args ...interface{}) error {
var err error
if r.Profiler != nil {
ctx := DatabaseProfilerContext{}.new(query, args...)
err = r.DB.Select(dest, query, args...)
err = r.DB.SelectContext(r.ctx, dest, query, args...)
r.Profiler.Post(ctx)
} else {
err = r.DB.Select(dest, query, args...)
err = r.DB.SelectContext(r.ctx, dest, query, args...)
}
// clear no rows returned error
if err == sql.ErrNoRows {
@ -201,10 +212,10 @@ func (r *DB) Get(dest interface{}, query string, args ...interface{}) error {
var err error
if r.Profiler != nil {
ctx := DatabaseProfilerContext{}.new(query, args...)
err = r.DB.Get(dest, query, args...)
err = r.DB.GetContext(r.ctx, dest, query, args...)
r.Profiler.Post(ctx)
} else {
err = r.DB.Get(dest, query, args...)
err = r.DB.GetContext(r.ctx, dest, query, args...)
}
// clear no rows returned error
if err == sql.ErrNoRows {

View File

@ -34,6 +34,7 @@ type errorMessage struct {
type Options struct {
Pretty bool // formats JSON output with indentation
Trace bool // prints a stack backtrace if exists (pkg/errors)
Logger func(error)
}
var config Options
@ -101,7 +102,11 @@ func JSON(w http.ResponseWriter, responses ...interface{}) {
result = value
case error:
// main key is "error"
result, err = encode(errorResponse(errors.WithStack(value)))
errWithStack := errors.WithStack(value)
if config.Logger != nil {
config.Logger(errWithStack)
}
result, err = encode(errorResponse(errWithStack))
case successMessage:
// main key is "success"
result, err = encode(value)

View File

@ -1,7 +1,7 @@
#!/bin/bash
set -e
go test ./prof* -v -cover
go test ./sonyflake* -v -cover
go test ./database* ./profiler.go -v -cover
go test ./resputil -v -cover -coverprofile=coverage.out
gotest ./prof* -v -cover
gotest ./sonyflake* -v -cover
gotest ./database* ./profiler.go -v -cover
gotest ./resputil -v -cover -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html

View File

@ -733,32 +733,67 @@ func (f *SettingsFrame) IsAck() bool {
return f.FrameHeader.Flags.Has(FlagSettingsAck)
}
func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
f.checkValid()
buf := f.p
for len(buf) > 0 {
settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
if settingID == s {
return binary.BigEndian.Uint32(buf[2:6]), true
for i := 0; i < f.NumSettings(); i++ {
if s := f.Setting(i); s.ID == id {
return s.Val, true
}
buf = buf[6:]
}
return 0, false
}
// Setting returns the setting from the frame at the given 0-based index.
// The index must be >= 0 and less than f.NumSettings().
func (f *SettingsFrame) Setting(i int) Setting {
buf := f.p
return Setting{
ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
}
}
func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
// HasDuplicates reports whether f contains any duplicate setting IDs.
func (f *SettingsFrame) HasDuplicates() bool {
num := f.NumSettings()
if num == 0 {
return false
}
// If it's small enough (the common case), just do the n^2
// thing and avoid a map allocation.
if num < 10 {
for i := 0; i < num; i++ {
idi := f.Setting(i).ID
for j := i + 1; j < num; j++ {
idj := f.Setting(j).ID
if idi == idj {
return true
}
}
}
return false
}
seen := map[SettingID]bool{}
for i := 0; i < num; i++ {
id := f.Setting(i).ID
if seen[id] {
return true
}
seen[id] = true
}
return false
}
// ForeachSetting runs fn for each setting.
// It stops and returns the first error.
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
f.checkValid()
buf := f.p
for len(buf) > 0 {
if err := fn(Setting{
SettingID(binary.BigEndian.Uint16(buf[:2])),
binary.BigEndian.Uint32(buf[2:6]),
}); err != nil {
for i := 0; i < f.NumSettings(); i++ {
if err := fn(f.Setting(i)); err != nil {
return err
}
buf = buf[6:]
}
return nil
}

View File

@ -1487,6 +1487,12 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
}
return nil
}
if f.NumSettings() > 100 || f.HasDuplicates() {
// This isn't actually in the spec, but hang up on
// suspiciously large settings frames or those with
// duplicate entries.
return ConnectionError(ErrCodeProtocol)
}
if err := f.ForeachSetting(sc.processSetting); err != nil {
return err
}