diff --git a/go.mod b/go.mod index 1a701a403..e14e911eb 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d github.com/crusttech/go-oidc v0.0.0-20180918092017-982855dad3e1 github.com/davecgh/go-spew v1.1.1 + github.com/deckarep/golang-set v1.7.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/disintegration/imaging v1.6.0 github.com/edwvee/exiffix v0.0.0-20180602190213-b57537c92a6b @@ -43,7 +44,6 @@ require ( github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 github.com/lib/pq v1.1.0 github.com/markbates/goth v1.50.0 - github.com/mattn/go-colorable v0.1.7 // indirect github.com/mattn/go-sqlite3 v1.14.0 github.com/minio/minio-go/v6 v6.0.39 github.com/mitchellh/copystructure v1.0.0 // indirect @@ -52,7 +52,6 @@ require ( github.com/pkg/errors v0.8.1 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/prometheus/client_golang v0.9.3 - github.com/rakyll/gotest v0.0.5 // indirect github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect github.com/smartystreets/goconvey v1.6.4 // indirect github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 @@ -63,7 +62,6 @@ require ( github.com/steinfletcher/apitest v1.3.8 github.com/steinfletcher/apitest-jsonpath v1.3.0 github.com/stretchr/testify v1.6.1 - github.com/titpetric/factory v0.0.0-20190828134837-8466c9bef13f go.uber.org/atomic v1.6.0 go.uber.org/zap v1.15.0 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 diff --git a/go.sum b/go.sum index 6aa899014..62d14c3cd 100644 --- a/go.sum +++ b/go.sum @@ -63,8 +63,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v0.3.17 h1:NGWgggJJqTofUcTV1E7hkk2zVjZ54EfJa1z5O3z6By4= @@ -83,8 +81,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -180,15 +176,6 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= github.com/markbates/goth v1.50.0 h1:KCAErbDdHh11gQAJs/GV73LCv4NwA7Z6wNZAU32ggMc= github.com/markbates/goth v1.50.0/go.mod h1:zZmAw0Es0Dpm7TT/4AdN14QrkiWLMrrU9Xei1o+/mdA= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= @@ -238,8 +225,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rakyll/gotest v0.0.5 h1:+BrdqPxKPDaxvhtIiVzfiYXLhi4BrSOqdwaEiA7qjpk= -github.com/rakyll/gotest v0.0.5/go.mod h1:SkoesdNCWmiD4R2dljIUcfSnNdVZ12y8qK4ojDkc2Sc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= @@ -275,8 +260,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/titpetric/factory v0.0.0-20190828134837-8466c9bef13f h1:sTgdEUlmmNSU3QKe8n20jR26zYEKw6ciSuj919XobV4= -github.com/titpetric/factory v0.0.0-20190828134837-8466c9bef13f/go.mod h1:VFd2XRrQZoX9cOxpeZezKpOlXDwU/dbRejKLjwP+xY8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= @@ -340,7 +323,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/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= @@ -350,9 +332,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff h1:1CPUrky56AcgSpxz/KfgzQWzfG09u5YOL8MvPYBlrL8= @@ -408,8 +387,6 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0= google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/vendor/github.com/titpetric/factory/.drone.yml b/vendor/github.com/titpetric/factory/.drone.yml deleted file mode 100644 index 3e65f43a8..000000000 --- a/vendor/github.com/titpetric/factory/.drone.yml +++ /dev/null @@ -1,32 +0,0 @@ -workspace: - base: /factory - -kind: pipeline -name: crust - -steps: -- name: build - image: golang:1.12-alpine - pull: always - environment: - CGO_ENABLED: 0 - GOOS: linux - GOARCH: amd64 - GOPROXY: https://proxy.golang.org - CI: travis - commands: - - go fmt ./... - - go test ./... -v -cover --tags="integration" - -services: -- name: factory-db - pull: always - image: percona:8.0 - command: [ "--innodb_lock_wait_timeout=2" ] - ports: - - 3306 - environment: - MYSQL_ROOT_PASSWORD: bRxJ37sJ6Qu4 - MYSQL_DATABASE: factory - MYSQL_USER: factory - MYSQL_PASSWORD: factory diff --git a/vendor/github.com/titpetric/factory/.gitignore b/vendor/github.com/titpetric/factory/.gitignore deleted file mode 100644 index 762713d6c..000000000 --- a/vendor/github.com/titpetric/factory/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/vendor -/coverage.* -/Gopkg.* -/.env \ No newline at end of file diff --git a/vendor/github.com/titpetric/factory/LICENSE b/vendor/github.com/titpetric/factory/LICENSE deleted file mode 100644 index 37219cf11..000000000 --- a/vendor/github.com/titpetric/factory/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2017+ Tit Petric - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/vendor/github.com/titpetric/factory/Makefile b/vendor/github.com/titpetric/factory/Makefile deleted file mode 100644 index 064f4a147..000000000 --- a/vendor/github.com/titpetric/factory/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: all - -all: - drone exec diff --git a/vendor/github.com/titpetric/factory/README.md b/vendor/github.com/titpetric/factory/README.md deleted file mode 100644 index 4d4bdb2d9..000000000 --- a/vendor/github.com/titpetric/factory/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# factory - -Go factories for some common things which I use. - -- Database (sqlx + mysql & pq) + utility functions -- Database query profiler for Stdout or Memory ([]string) -- Sonyflake ID generator for uint64 ids - -Written by [@TitPetric](https://twitter.com/TitPetric) and licensed under the permissive [WTFPL](http://www.wtfpl.net/txt/copying/). diff --git a/vendor/github.com/titpetric/factory/database.go b/vendor/github.com/titpetric/factory/database.go deleted file mode 100644 index 95f0d5de1..000000000 --- a/vendor/github.com/titpetric/factory/database.go +++ /dev/null @@ -1,578 +0,0 @@ -package factory - -import ( - "context" - "fmt" - "reflect" - "strings" - "time" - - "database/sql" - - "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" - - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" - - "github.com/titpetric/factory/logger" -) - -// DatabaseCredential is a configuration struct for a database connection -type DatabaseCredential struct { - DSN string - DriverName string - Connector func() (*sql.DB, error) -} - -// DatabaseFactory contains all database credentials and instances -type DatabaseFactory struct { - credentials map[string]DatabaseCredential - instances map[string]*DB -} - -// The default database factory -var Database *DatabaseFactory - -func init() { - Database = &DatabaseFactory{} - Database.credentials = make(map[string]DatabaseCredential) - Database.instances = make(map[string]*DB) -} - -// Add a new named database credential to the database factory -// -// The function will store a named database credential for use with -// the Get function. Generally you'd need to call Add at least once. -// In order to set the default database credential, use "default" as -// the first parameter. -// -// Example: -// -// ``` -// factory.Database.Add("default", factory.DatabaseCredential{"mysql", "sqlapi:sqlapi@tcp(db1:3306)/sqlapi?collation=utf8mb4_general_ci"}) -// ``` -// -// By default, additional options will be added to the credentials DSN: -// -// - collation will be set to `utf8_general_ci` -// - parseTime will be set to `true` -// - loc will be set to `Local` -// -// If your passed DSN will include any of these options, the default values will not -// be applied, and your custom settings will be honored. -func (r *DatabaseFactory) Add(name string, credentials DatabaseCredential) { - credentials.DSN = r.CleanDSN(credentials.DriverName, credentials.DSN) - r.credentials[name] = credentials -} - -func (r *DatabaseFactory) CleanDSN(driverName string, dsn string) string { - addOption := func(s, match, option string) string { - if !strings.Contains(s, match) { - s += option - } - return s - } - - dsn = addOption(dsn, "?", "?") - dsn = addOption(dsn, "collation=", "&collation=utf8_general_ci") - dsn = addOption(dsn, "parseTime=", "&parseTime=true") - dsn = addOption(dsn, "loc=", "&loc=Local") - dsn = strings.Replace(dsn, "?&", "?", 1) - return dsn -} - -// getCredentials returns the DatabaseCredential{} for a given db name -func (r *DatabaseFactory) getCredentials(name string) (*DatabaseCredential, error) { - if value, ok := r.credentials[name]; ok { - return &value, nil - } - return nil, errors.New("No configuration found for database: " + name) -} - -// Get returns a database connection -// -// If you don't request a database connection by name, `factory.Database.Get()` will -// return the connection with the name "default". If you supply one or more names as -// the parameter, the first successful connection will be returned. -// -// It is fine to call this function per request, as a singleton instance is returned -// for each call with the same parameters. -// -// This behavior enables sharding workloads between hosts. One could randomize the -// parameters using [math/rand#Shuffle](https://tip.golang.org/pkg/math/rand/#Shuffle), or -// provide a consistent hashing method based on server hostname/IP, or even go so far -// to retrieve the hosts to connect to from some sort of inventory like etcd. -// -// The most general use case is that you will only call `factory.Database.Get()` once, -// and then pass the resulting `*DB` forward in your application. Requesting custom named -// connections also provides a way to access different parts of the database, or different -// database altogether, depending on your microservice data distribution. -func (r *DatabaseFactory) Get(dbName ...string) (*DB, error) { - names := dbName - if len(names) == 0 { - names = []string{"default"} - } - for _, name := range names { - if value, ok := r.instances[name]; ok { - return value, nil - } - - credentials, err := r.getCredentials(name) - if err != nil { - return nil, err - } - - if credentials.DriverName == "" { - return nil, errors.New("Credentials missing DriverName") - } - - var handle *sqlx.DB - - switch true { - case credentials.Connector != nil: - db, err := credentials.Connector() - if err != nil { - return nil, errors.WithStack(err) - } - handle = sqlx.NewDb(db, credentials.DriverName) - default: - handle, err = sqlx.Connect(credentials.DriverName, credentials.DSN) - if err != nil { - return nil, errors.WithStack(err) - } - } - - r.instances[name] = &DB{ - handle, - context.Background(), - 0, - nil, - &sql.TxOptions{ - ReadOnly: false, - }, - logger.Silent{}, - } - return r.instances[name], nil - } - return nil, fmt.Errorf("No configuration found for database: %v", names) -} - -// MustGet is the same as Get, except it will panic on connection error -func (r *DatabaseFactory) MustGet(dbName ...string) *DB { - db, err := r.Get(dbName...) - if err != nil { - panic(err) - } - return db -} - -// DB struct encapsulates sqlx.DB to add new functions -type DB struct { - *sqlx.DB - - ctx context.Context - - inTx int32 - Tx *sqlx.Tx - TxOpts *sql.TxOptions - - logger logger.Logger -} - -// Quiet will return a DB handle without a logger -func (r *DB) Quiet() *DB { - return &DB{ - r.DB, - r.ctx, - r.inTx, - r.Tx, - r.TxOpts, - logger.Silent{}, - } -} - -// With will return a DB handle with a bound context (throw-away) -func (r *DB) With(ctx context.Context) *DB { - return &DB{ - r.DB, - ctx, - r.inTx, - r.Tx, - r.TxOpts, - r.logger, - } -} - -// Set a custom logger -func (r *DB) SetLogger(logger logger.Logger) { - r.logger = logger -} - -// Begin will create a transaction in the DB with a context -func (r *DB) Begin() (err error) { - if r.inTx > 0 { - _, err = r.Exec(fmt.Sprintf("SAVEPOINT sp_%d", r.inTx)) - } - if r.inTx == 0 { - if r.ctx == nil { - r.Log(func() { - r.Tx, err = r.DB.Beginx() - }, "BEGIN;") - } else { - r.Log(func() { - r.Tx, err = r.DB.BeginTxx(r.ctx, r.TxOpts) - }, "BEGIN; -- with context") - } - } - if err != nil { - return errors.WithStack(err) - } - - r.inTx++ - return nil -} - -// Transaction will create a transaction and invoke a callback -func (r *DB) Transaction(callback func() error) (err error) { - var try int - - // Perform transaction statements - try = 0 - for { - // Start transaction - if err = r.Begin(); err != nil { - return - } - - if err = callback(); err == nil { - break - } - - try++ - if try > 3 { - r.logger.Log(r.ctx, fmt.Sprintf("Retried transaction %d times, aborting", try-1)) - break - } - - // Break out if the causer is not a MySQL error - cause, ok := (errors.Cause(err)).(*mysql.MySQLError) - if !ok { - r.logger.Log(r.ctx, "Returned error cause is not a MySQLError", logger.NewField("err", err)) - break - } - - // restart transaction: - // - 1205: lock within transaction (unit tested), - // - 1213: deadlock found - if cause.Number == 1205 || cause.Number == 1213 { - r.logger.Log(r.ctx, "Retrying transaction", logger.NewField("try", try), logger.NewField("cause", cause)) - r.Rollback() - time.Sleep(50 * time.Millisecond) - continue - } - - r.logger.Log(r.ctx, "Can't handle transaction error, aborting") - break - } - - if err != nil { - r.Rollback() - return err - } - return r.Commit() -} - -func (r *DB) Commit() (err error) { - if r.Tx != nil { - if r.inTx <= 1 { - r.Log(func() { - err = r.Tx.Commit() - }, "COMMIT;") - if err != nil { - return errors.WithStack(err) - } - r.Tx = nil - r.inTx = 0 - return nil - } - if _, err = r.Exec(fmt.Sprintf("RELEASE SAVEPOINT sp_%d", r.inTx-1)); err != nil { - return errors.WithStack(err) - } - r.inTx-- - return nil - } - return errors.WithStack(sql.ErrTxDone) -} - -func (r *DB) Rollback() (err error) { - if r.Tx != nil { - if r.inTx <= 1 { - r.Log(func() { - err = r.Tx.Rollback() - }, "ROLLBACK;") - if err != nil { - return errors.WithStack(err) - } - r.Tx = nil - r.inTx = 0 - return nil - } - if _, err = r.Exec(fmt.Sprintf("ROLLBACK SAVEPOINT sp_%d", r.inTx-1)); err != nil { - return errors.WithStack(err) - } - r.inTx-- - return nil - } - return errors.WithStack(sql.ErrTxDone) -} - -// SetFields will provide a string with SQL named bindings from a string slice -func (r *DB) SetFields(fields []string) string { - idx := 0 - sql := "" - for _, field := range fields { - if idx > 0 { - sql = sql + ", " - } - idx++ - sql = sql + field + "=:" + field - } - return sql -} - -// NamedExec adds profiling on top of the parent DB.NameExec -func (r *DB) NamedExec(query string, arg interface{}) (res sql.Result, err error) { - exec := func() (sql.Result, error) { - if r.Tx != nil { - return r.Tx.NamedExecContext(r.ctx, query, arg) - } - return r.DB.NamedExecContext(r.ctx, query, arg) - } - - r.Log(func() { - res, err = exec() - }, query, arg) - - return res, errors.Wrap(err, "exec query failed") -} - -// Exec adds profiling on top of the parent DB.Exec -func (r *DB) Exec(query string, args ...interface{}) (res sql.Result, err error) { - exec := func() (sql.Result, error) { - if r.Tx != nil { - return r.Tx.ExecContext(r.ctx, query, args...) - } - return r.DB.ExecContext(r.ctx, query, args...) - } - - r.Log(func() { - res, err = exec() - }, query, args...) - - return res, errors.Wrap(err, "exec query failed") -} - -// Select is a helper function that will ignore sql.ErrNoRows -func (r *DB) Select(dest interface{}, query string, args ...interface{}) error { - var err error - exec := func() error { - if r.Tx != nil { - return r.Tx.SelectContext(r.ctx, dest, query, args...) - } - return r.DB.SelectContext(r.ctx, dest, query, args...) - } - - r.Log(func() { - err = exec() - }, query, args...) - - // clear no rows returned error - if err == sql.ErrNoRows { - return nil - } - - return errors.Wrap(err, "select query failed") -} - -// Get is a helper function that will ignore sql.ErrNoRows -func (r *DB) Get(dest interface{}, query string, args ...interface{}) error { - var err error - exec := func() error { - if r.Tx != nil { - return r.Tx.GetContext(r.ctx, dest, query, args...) - } - return r.DB.GetContext(r.ctx, dest, query, args...) - } - - r.Log(func() { - err = exec() - }, query, args...) - - // clear no rows returned error - if err == sql.ErrNoRows { - return nil - } - - return errors.Wrap(err, "get query failed") -} - -// set uses reflection to iterate over struct fields tags, producing bindings for struct values -func (r *DB) set(data interface{}, allowed ...string) string { - set := r.setMap(data, allowed...) - return r.setImplode(", ", set) -} - -func (r *DB) tag(tag string) string { - if tag != "" && tag != "-" { - return strings.Split(tag, ",")[0] - } - return "" -} - -func (r *DB) setMap(data interface{}, allowed ...string) map[string]string { - message_value := reflect.ValueOf(data) - if message_value.Kind() == reflect.Ptr { - message_value = message_value.Elem() - } - - set := make(map[string]string) - length := message_value.NumField() - for i := 0; i < length; i++ { - fieldType := message_value.Type().Field(i) - if tag := r.tag(fieldType.Tag.Get("db")); tag != "" { - set[tag] = ":" + tag - } - } - - // limit only to allowed fields - if len(allowed) > 0 { - for tag, _ := range set { - canDelete := true - for _, key := range allowed { - if tag == key { - canDelete = false - break - } - } - if canDelete { - delete(set, tag) - } - } - } - - return set -} - -func (r *DB) setImplode(delimiter string, set map[string]string) string { - result := "" - count := 0 - for key, value := range set { - if count > 0 { - result = result + delimiter - } - result = result + key + "=" + value - count++ - } - return result -} - -// Update is a helper function which will issue an `update` statement to the db -func (r *DB) Update(table string, args interface{}, keys ...string) error { - var err error - if len(keys) == 0 { - return errors.New("Full-table update not supported") - } - set := r.setMap(args) - setWhere := make(map[string]string) - for _, key := range keys { - value, ok := set[key] - if !ok { - return errors.New("Can't update table " + table + " by key " + key + " (no such field in struct)") - } - delete(set, key) - setWhere[key] = value - } - if len(set) == 0 { - return errors.New("Encountered update struct with no fields") - } - query := "update " + table + " set " + r.setImplode(", ", set) + " where " + r.setImplode(" AND ", setWhere) - _, err = r.NamedExec(query, args) - return err -} - -// UpdatePartial is a helper function which will issue an `update` statement to the db -func (r *DB) UpdatePartial(table string, args interface{}, allowed []string, keys ...string) error { - var err error - if len(keys) == 0 { - return errors.New("Full-table update not supported") - } - set := r.setMap(args, allowed...) - setWhere := make(map[string]string) - for _, key := range keys { - value, ok := set[key] - if !ok { - return errors.New("Can't update table " + table + " by key " + key + " (no such field in struct)") - } - delete(set, key) - setWhere[key] = value - } - if len(set) == 0 { - return errors.New("Encountered update struct with no fields") - } - query := "update " + table + " set " + r.setImplode(", ", set) + " where " + r.setImplode(" AND ", setWhere) - _, err = r.NamedExec(query, args) - return err -} - -// Delete is a helper function which will issue an `delete` statement to the db -func (r *DB) Delete(table string, args interface{}, keys ...string) error { - var err error - if len(keys) == 0 { - return errors.New("Full-table delete not supported") - } - set := r.setMap(args) - setWhere := make(map[string]string) - for _, key := range keys { - value, ok := set[key] - if !ok { - return errors.New("Can't update table " + table + " by key " + key + " (no such field in struct)") - } - delete(set, key) - setWhere[key] = value - } - query := "delete from " + table + " where " + r.setImplode(" AND ", setWhere) - _, err = r.NamedExec(query, args) - return err -} - -// Replace is a helper function which will issue an `replace` statement to the database -func (r *DB) Replace(table string, args interface{}) error { - var err error - query := "replace into " + table + " set " + r.set(args) - _, err = r.NamedExec(query, args) - return err -} - -// Insert is a helper function which will issue an `insert` statement to the database -func (r *DB) Insert(table string, args interface{}) error { - var err error - query := "insert into " + table + " set " + r.set(args) - _, err = r.NamedExec(query, args) - return err -} - -// InsertIgnore is a helper function which will issue an `insert ignore` statement to the database -func (r *DB) InsertIgnore(table string, args interface{}) error { - var err error - query := "insert ignore into " + table + " set " + r.set(args) - _, err = r.NamedExec(query, args) - return err -} - -func (r *DB) Log(callback func(), query string, args ...interface{}) { - start := time.Now() - callback() - duration := time.Since(start).Seconds() - r.logger.Log(r.ctx, query, logger.NewField("duration", duration), logger.NewField("args", args)) -} diff --git a/vendor/github.com/titpetric/factory/database_connector.go b/vendor/github.com/titpetric/factory/database_connector.go deleted file mode 100644 index 2f6c1dcf0..000000000 --- a/vendor/github.com/titpetric/factory/database_connector.go +++ /dev/null @@ -1,106 +0,0 @@ -package factory - -import ( - "context" - "fmt" - "log" - "regexp" - "time" - - "github.com/pkg/errors" - "github.com/titpetric/factory/logger" -) - -// DatabaseConnectionOptions is a configuration struct for connection retry -type DatabaseConnectionOptions struct { - DSN string - DriverName string - Logger string - - Retries int - RetryTimeout time.Duration - ConnectTimeout time.Duration -} - -var ( - dsnMasker = regexp.MustCompile("(.)(?:.*)(.):(.)(?:.*)(.)@") -) - -func (df *DatabaseFactory) TryToConnect(ctx context.Context, name string, options *DatabaseConnectionOptions) (db *DB, err error) { - df.Add(name, DatabaseCredential{ - DSN: options.DSN, - DriverName: options.DriverName, - }) - - var ( - connErrCh = make(chan error, 1) - ) - - // We'll not add this to the general log because we do not want to carry it with us for every query. - dsnField := fmt.Sprintf("dsn=%s", dsnMasker.ReplaceAllString(options.DSN, "$1****$2:$3****$4@")) - - defer close(connErrCh) - - log.Println("connecting to database", dsnField) - - go func() { - var ( - try = 0 - ) - - for { - try++ - - if options.Retries <= try { - err = errors.Errorf("could not connect to %q, in %d tries", name, try) - return - } - - db, err = df.Get(name) - if err != nil { - log.Println( - "could not connect to the database", - err, - dsnField, - fmt.Sprintf("try=%d", try), - ) - - select { - case <-ctx.Done(): - // Forced break - break - case <-time.After(options.RetryTimeout): - // Wait before next try - continue - } - } - - break - } - - connErrCh <- err - }() - - select { - case err = <-connErrCh: - break - case <-time.After(options.ConnectTimeout): - // Wait before next try - return nil, errors.Errorf("db init for %q timed out", name) - case <-ctx.Done(): - return nil, errors.Errorf("db connection for %q cancelled", name) - } - - switch options.Logger { - case "stdout": - db.SetLogger(logger.Default{}) - default: - db.SetLogger(logger.Silent{}) - } - - if err != nil { - return nil, err - } - - return db, nil -} diff --git a/vendor/github.com/titpetric/factory/go.mod b/vendor/github.com/titpetric/factory/go.mod deleted file mode 100644 index 382f7f880..000000000 --- a/vendor/github.com/titpetric/factory/go.mod +++ /dev/null @@ -1,12 +0,0 @@ -module github.com/titpetric/factory - -go 1.12 - -require ( - github.com/deckarep/golang-set v1.7.1 // indirect - github.com/go-sql-driver/mysql v1.4.1 - github.com/jmoiron/sqlx v1.2.0 - github.com/lib/pq v1.0.0 - github.com/pkg/errors v0.8.1 - github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 -) diff --git a/vendor/github.com/titpetric/factory/go.sum b/vendor/github.com/titpetric/factory/go.sum deleted file mode 100644 index 05aba676f..000000000 --- a/vendor/github.com/titpetric/factory/go.sum +++ /dev/null @@ -1,15 +0,0 @@ -github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= -github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009 h1:3wBL/e/qjpSYaXacpbIV+Bsj/nwQ4UO1llG/av54zzw= -github.com/sony/sonyflake v0.0.0-20181109022403-6d5bd6181009/go.mod h1:dVvZuWJd174umvm5g8CmZD6S2GWwHKtpK/0ZPHswuNo= diff --git a/vendor/github.com/titpetric/factory/logger/default.go b/vendor/github.com/titpetric/factory/logger/default.go deleted file mode 100644 index 185066a58..000000000 --- a/vendor/github.com/titpetric/factory/logger/default.go +++ /dev/null @@ -1,20 +0,0 @@ -package logger - -import ( - "context" - "log" -) - -type ( - Default struct{} -) - -func (Default) Log(ctx context.Context, msg string, fields ...Field) { - args := make([]interface{}, len(fields)+1) - args[0] = msg - for key, value := range fields { - args[key+1] = value - } - // fields satisfy fmt.Stringer as well - log.Println(args...) -} diff --git a/vendor/github.com/titpetric/factory/logger/field.go b/vendor/github.com/titpetric/factory/logger/field.go deleted file mode 100644 index d9e8a8210..000000000 --- a/vendor/github.com/titpetric/factory/logger/field.go +++ /dev/null @@ -1,28 +0,0 @@ -package logger - -import ( - "fmt" -) - -type ( - field struct { - name string - value interface{} - } -) - -func NewField(name string, value interface{}) Field { - return field{name, value} -} - -func (f field) Name() string { - return f.name -} - -func (f field) Value() interface{} { - return f.value -} - -func (f field) String() string { - return fmt.Sprintf("%s=%v", f.name, f.value) -} diff --git a/vendor/github.com/titpetric/factory/logger/interface.go b/vendor/github.com/titpetric/factory/logger/interface.go deleted file mode 100644 index 35e9dab7a..000000000 --- a/vendor/github.com/titpetric/factory/logger/interface.go +++ /dev/null @@ -1,23 +0,0 @@ -package logger - -import ( - "context" - "fmt" -) - -type ( - Logger interface { - Log(ctx context.Context, message string, fields ...Field) - } - - Field interface { - Name() string - Value() interface{} - - fmt.Stringer - } -) - -func New() Logger { - return Default{} -} diff --git a/vendor/github.com/titpetric/factory/logger/silent.go b/vendor/github.com/titpetric/factory/logger/silent.go deleted file mode 100644 index 586b98a3e..000000000 --- a/vendor/github.com/titpetric/factory/logger/silent.go +++ /dev/null @@ -1,12 +0,0 @@ -package logger - -import ( - "context" -) - -type ( - Silent struct{} -) - -func (Silent) Log(ctx context.Context, msg string, fields ...Field) { -} diff --git a/vendor/github.com/titpetric/factory/resputil/README.md b/vendor/github.com/titpetric/factory/resputil/README.md deleted file mode 100644 index f9585b0e9..000000000 --- a/vendor/github.com/titpetric/factory/resputil/README.md +++ /dev/null @@ -1,187 +0,0 @@ -# resputil - -The package provides utilities to respond with some structured JSON payloads. -By default, anything you pass to `JSON` will be encapsulated depending on the type. - -~~~go -func JSON(w http.ResponseWriter, responses ...interface{}) { -~~~ - -The `response` variadic parameter may be any of the following: - -- string -- error -- int -- struct -- nil -- interface -- func() error -- func() (interface{}, error) -- func() ([]byte, error) - -It will output the first non-empty value. In the case where the result is taken -from a `interface{}, error` return, it will first output the error if it's not -empty, and then output the value, *even if empty*. For all other cases it will -skip to the next item in the responses parameter. - -A parameter of the type of `func() ([]byte, error)` will not return a wrapped structure. -It's assumed the `[]byte` result is an as-is payload which should be returned. A typical -use case is to return the output of `json.Marshal` which matches this signature. - -The motivation behind it is to provide more reasonable error handling, when you -want to break out of your function with less code. It's in part an attempt to get -rid of all the `if err != nil {` checks in your code, but at the same time it's -also something that changes how your code might be laid in order to fully take -advantage of what it gives you. - -For example, when writing APIs, you might structure your API call into several -logical units, that have different responsibilities: - -- request validation (parameters) -- request processing (issuing SQL queries based on parameters) - - this one may be significantly broken down into many stages -- the actual response payload - -Taking advantage of scope, this may look like this: - -~~~go -mux.HandleFunc("/api/*", func(w http.ResponseWriter, r *http.Request) { - owner := login.Decode(r) - call := chi.URLParam(r, "*") - - // validate request - validate := func() error { - if owner == "" { - return errors.New("Missing login info. Try to relogin") - } - if call == "" { - return errors.New("Unknown API call") - } - if r.Method == "POST" { - return errors.Wrap(r.ParseForm(), "Error parsing POST data") - } - return nil - } - - // process request - process := func() (interface{}, error) { - params := map[string]interface{}{ - "owner": owner, - } - urlQuery := r.URL.Query() - for name, param := range urlQuery { - params[name] = param[0] - } - postVars := r.Form - for name, param := range postVars { - params[name] = param[0] - } - return sqlAPI(call, params) - } - - // process request - resputil.JSON(w, validate, process) -}) -~~~ - -Since `validate` and `process` are closures, they may access anything within the scope of -their parent function. This means that you can have a `RequestParameters` struct, a response -struct, and actually extend the logic of this further. This would be one possible way: - -~~~go - // Parameters - params := &CommentListThread{ - CommentList: &CommentList{ - NewsID: chi.URLParam(r, "id"), - SessionID: r.URL.Query().Get("session_id"), - Sort: r.URL.Query().Get("sort"), - Order: r.URL.Query().Get("order"), - PageNumber: parseInt64(r.URL.Query().Get("pageNumber")), - PageSize: parseInt64(r.URL.Query().Get("pageSize")), - }, - SelfID: parseInt64(r.URL.Query().Get("self_id")), - } - - /* steps: - - 0. validate inputs - 1. with self_id=0 parameters: - a. get comments with self_id 0 in the pagenumber/pagesize range, - b. get all child comments with parent comment IDs, - c. add 5 comments with date/asc to parent comments - d. return comments data - 2. with self_id>0 parameters: - a. get comments with self_id X in the pagenumber/pagesize range, - b. return comments data - - */ - - // Parameters are included in the response - result := params - - validate := func() error { - if !is(params.Sort, "date", "rating") { - params.Sort = "date" - } - if !is(params.Order, "asc", "desc") { - params.Order = "asc" - } - if params.PageNumber < 0 { - params.PageNumber = 0 - } - if params.PageSize < 10 { - params.PageSize = 10 - } - if params.PageSize > 100 { - params.PageSize = 100 - } - return nil - } - - // more code here ... - - resputil.JSON(w, validate, process, addReplies, result) -~~~ - -The parent function is broken down into closures, that represent some stage of the issued -request. Depending on what works for you, each stage individually can produce an error using -a `func() error` declaration like shown here. If a non-empty value is returned, it will -be encoded into JSON and written to the HTTP output. - -This pattern of use also allows a more functional approach to what you're responding with. For example, -if you favor something closer to an ORM approach, then you could do something more similar to this: - -~~~go -func (p *ProjectHTTP) create(w http.ResponseWriter, r *http.Request) { - project := Project{}.New() - resputil.JSON( - w, - project.SetName(r.PostFormValue("name")), - project.Save(), - project, - ) -} -~~~ - -In this case, both `SetName` and `Save` will be invoked, regardless of the fact if `SetName` returned -an error. Care should be taken between mixing `error` and `func() error` parameters, due to the order -in which they will be invoked. In the above case, both SetName and Save are invoked before `JSON()`, but -if we would omit `()` from `Save()`, the Save function would be invoked by `JSON()`. - -## Tests - -The package has 100% code coverage, but errors are possible. Due to the fact that the implementation is -aimed at generic "take anything" use, errors may occur at runtime. - -## Other notes - -- The package makes use of `pkg/errors`, returning a stack trace in the JSON response if configured with `SetConfig` -- There are helper functions `OK()` and `Success(string)` to format successful messages (`{ "success": { "message": "..." } }`) -- Errors will be formatted as `{ "error": { "message": "..." } }` [according to some Google conventions](https://cloud.google.com/storage/docs/json_api/v1/status-codes) which may or may not have a RFC -- HTTP response codes are not honored, you will always get a 200 OK response and a descriptive JSON payload -- valid responses are nested within `{ "response": ... }` -- if the set of all passed data to respond with it empty or all it's values are empty, `{ "response": false }` will be returned - -## License - -Written by [@TitPetric](https://twitter.com/TitPetric) and licensed under the permissive [WTFPL](http://www.wtfpl.net/txt/copying/). \ No newline at end of file diff --git a/vendor/github.com/titpetric/factory/resputil/resputil.go b/vendor/github.com/titpetric/factory/resputil/resputil.go deleted file mode 100644 index 62e0c6825..000000000 --- a/vendor/github.com/titpetric/factory/resputil/resputil.go +++ /dev/null @@ -1,169 +0,0 @@ -package resputil - -import ( - "encoding/json" - "fmt" - "net/http" - - "github.com/pkg/errors" -) - -// Exported error messages -const ( - E_EMPTY_TRACE = "no stack trace available" -) - -type stackTracer interface { - StackTrace() errors.StackTrace -} - -type successMessage struct { - Success struct { - Message string `json:"message"` - } `json:"success"` -} - -type errorMessage struct { - Error struct { - Message string `json:"message"` - Trace string `json:"trace,omitempty"` - } `json:"error"` -} - -// Options struct / configuration parameters -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 - -// SetConfig updates package options in use -func SetConfig(options Options) { - config = options -} - -// getTrace prints the first available stack trace if any -func getTrace(errs ...error) string { - for _, err := range errs { - if err != nil { - terr, ok := err.(stackTracer) - if ok { - return fmt.Sprintf("%+v", terr.StackTrace()) - } - } - } - return E_EMPTY_TRACE -} - -// error returns a structured error for API responses -func errorResponse(err ...error) errorMessage { - response := errorMessage{} - // add stack trace to the response if available and enabled - response.Error.Message = "Unknown error" - if len(err) > 0 { - if config.Trace { - response.Error.Trace = getTrace(errors.Cause(err[0]), err[0]) - } - response.Error.Message = err[0].Error() - } - return response -} - -// Success returns a structured success message for API responses -func Success(success ...string) successMessage { - response := successMessage{} - response.Success.Message = "OK" - if len(success) > 0 { - response.Success.Message = success[0] - } - return response -} - -// OK returns the default Success message -func OK() successMessage { - return Success() -} - -// JSON responds with the first non-nil payload, formats error messages -func JSON(w http.ResponseWriter, responses ...interface{}) { - respond := func(payload interface{}) { - var result []byte - var err error - encode := func(payload interface{}) ([]byte, error) { - if config.Pretty { - return json.MarshalIndent(payload, "", "\t") - } - return json.Marshal(payload) - } - switch value := payload.(type) { - case []byte: - result = value - case error: - // main key is "error" - 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) - default: - // main key is "response" - result, err = encode(struct { - Response interface{} `json:"response"` - }{value}) - } - if err != nil { - result, _ = encode(errorResponse(errors.WithStack(err))) - } - w.Header().Set("Content-Type", "application/json") - w.Write(result) - } - - for _, response := range responses { - switch value := response.(type) { - case nil: - // this will match a nil error - continue - case func() ([]byte, error): - result, err := value() - JSON(w, err, result) - case func() (interface{}, error): - result, err := value() - JSON(w, err, result) - case func() error: - err := value() - if err == nil { - continue - } - respond(err) - case *error: - if *value == nil { - continue - } - respond(*value) - case error: - respond(value) - case string: - if value == "" { - continue - } - respond(value) - case bool: - if !value { - continue - } - respond(value) - case successMessage: - respond(value) - default: - respond(value) - } - // Exit on the first output... - return - } - respond(false) -} diff --git a/vendor/github.com/titpetric/factory/semaphore.go b/vendor/github.com/titpetric/factory/semaphore.go deleted file mode 100644 index dce7a5b28..000000000 --- a/vendor/github.com/titpetric/factory/semaphore.go +++ /dev/null @@ -1,20 +0,0 @@ -package factory - -import ( - "sync/atomic" -) - -// Semaphore provides a run-once type of flag (atomic) -type Semaphore struct { - semaphore int32 -} - -// CanRun will allow a caller to proceed -func (l *Semaphore) CanRun() bool { - return atomic.CompareAndSwapInt32(&l.semaphore, 0, 1) -} - -// Done finishes the run -func (l *Semaphore) Done() { - atomic.CompareAndSwapInt32(&l.semaphore, 1, 0) -} diff --git a/vendor/github.com/titpetric/factory/sonyflake.go b/vendor/github.com/titpetric/factory/sonyflake.go deleted file mode 100644 index 26d8dd3ab..000000000 --- a/vendor/github.com/titpetric/factory/sonyflake.go +++ /dev/null @@ -1,36 +0,0 @@ -package factory - -import ( - "github.com/sony/sonyflake" - "time" -) - -// SonyflakeFactory is a configuration struct -type SonyflakeFactory struct { - *sonyflake.Sonyflake -} - -// Sonyflake is the active ID generator instance -var Sonyflake *SonyflakeFactory - -func init() { - Sonyflake = &SonyflakeFactory{ - sonyflake.NewSonyflake(sonyflake.Settings{ - StartTime: time.Unix(1503550784, 0), - }), - } -} - -// NextID returns uint64 ID, escalates possible error to a panic -func (s *SonyflakeFactory) NextID() uint64 { - // sonyflake errors out only when the time overflows, that will - // occur in approximately 174 years after the custom epoch. - // If the 10ms keyspace is exhausted, NextID will sleep and return - // an ID from the next interval. It can't fail, because the generator - // is protected by a Mutex. - id, err := s.Sonyflake.NextID() - if err != nil { - panic(err) - } - return id -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 92ce1b288..59903224d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -168,10 +168,6 @@ github.com/steinfletcher/apitest-jsonpath # github.com/stretchr/testify v1.6.1 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/titpetric/factory v0.0.0-20190828134837-8466c9bef13f -github.com/titpetric/factory -github.com/titpetric/factory/logger -github.com/titpetric/factory/resputil # go.uber.org/atomic v1.6.0 go.uber.org/atomic # go.uber.org/multierr v1.5.0