go vendor
This commit is contained in:
80
vendor/github.com/revel/modules/orm/gorm/README.md
generated
vendored
Normal file
80
vendor/github.com/revel/modules/orm/gorm/README.md
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
modules/gorm
|
||||
===============
|
||||
|
||||
[Gorm](http://jinzhu.me/gorm) module
|
||||
|
||||
## Activation
|
||||
```ini
|
||||
module.gorm = github.com/revel/modules/orm/gorm
|
||||
```
|
||||
|
||||
## Drivers
|
||||
|
||||
* sqlite3
|
||||
* postgres
|
||||
* mysql
|
||||
|
||||
## Configuration file
|
||||
|
||||
```ini
|
||||
# Database config
|
||||
db.autoinit=true # default=true
|
||||
db.driver=sqlite # mysql, postgres, sqlite3
|
||||
db.host=localhost # Use db.host /tmp/app.db is your driver is sqlite
|
||||
db.user=dbuser
|
||||
db.name=dbname
|
||||
db.password=dbpassword
|
||||
|
||||
```
|
||||
|
||||
## Example usage with transactions
|
||||
```go
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
gormc "github.com/revel/modules/gorm/orm/app/controllers"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
gormc.TxnController
|
||||
}
|
||||
|
||||
type Toy struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c App) Index() revel.Result {
|
||||
c.Txn.LogMode(true)
|
||||
c.Txn.AutoMigrate(&Toy{})
|
||||
c.Txn.Save(&Toy{Name: "Fidget spinner"})
|
||||
|
||||
return c.Render()
|
||||
}
|
||||
```
|
||||
|
||||
## Example usage without transactions
|
||||
```go
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
gormc "github.com/revel/modules/gorm/orm/app/controllers"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
gormc.Controller
|
||||
}
|
||||
|
||||
type Toy struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c App) Index() revel.Result {
|
||||
c.DB.LogMode(true)
|
||||
c.DB.AutoMigrate(&Toy{})
|
||||
c.DB.Save(&Toy{Name: "Fidget spinner"})
|
||||
|
||||
return c.Render()
|
||||
}
|
||||
```
|
||||
84
vendor/github.com/revel/modules/orm/gorm/app/controllers/gorm.go
generated
vendored
Normal file
84
vendor/github.com/revel/modules/orm/gorm/app/controllers/gorm.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package gormcontroller
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
gormdb "github.com/revel/modules/orm/gorm/app"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
// Controller is a Revel controller with a pointer to the opened database
|
||||
type Controller struct {
|
||||
*revel.Controller
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func (c *Controller) setDB() revel.Result {
|
||||
c.DB = gormdb.DB
|
||||
return nil
|
||||
}
|
||||
|
||||
// TxnController is a Revel controller with database transaction support (begin, commit and rollback)
|
||||
type TxnController struct {
|
||||
*revel.Controller
|
||||
Txn *gorm.DB
|
||||
}
|
||||
|
||||
// Begin begins a DB transaction
|
||||
func (c *TxnController) Begin() revel.Result {
|
||||
|
||||
txn := gormdb.DB.Begin()
|
||||
if txn.Error != nil {
|
||||
c.Log.Panic("Transaction begine error","error",txn.Error)
|
||||
}
|
||||
|
||||
c.Txn = txn
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit commits the database transation
|
||||
func (c *TxnController) Commit() revel.Result {
|
||||
if c.Txn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Txn.Commit()
|
||||
if c.Txn.Error != nil && c.Txn.Error != sql.ErrTxDone {
|
||||
fmt.Println(c.Txn.Error)
|
||||
panic(c.Txn.Error)
|
||||
}
|
||||
|
||||
c.Txn = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rollback rolls back the transaction (eg. after a panic)
|
||||
func (c *TxnController) Rollback() revel.Result {
|
||||
if c.Txn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.Txn.Rollback()
|
||||
if c.Txn.Error != nil && c.Txn.Error != sql.ErrTxDone {
|
||||
fmt.Println(c.Txn.Error)
|
||||
panic(c.Txn.Error)
|
||||
}
|
||||
|
||||
c.Txn = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
revel.OnAppStart(func() {
|
||||
if revel.Config.BoolDefault("db.autoinit", true) {
|
||||
gormdb.InitDB()
|
||||
revel.InterceptMethod((*TxnController).Begin, revel.BEFORE)
|
||||
revel.InterceptMethod((*TxnController).Commit, revel.AFTER)
|
||||
revel.InterceptMethod((*TxnController).Rollback, revel.FINALLY)
|
||||
|
||||
revel.InterceptMethod((*Controller).setDB, revel.BEFORE)
|
||||
}
|
||||
})
|
||||
}
|
||||
72
vendor/github.com/revel/modules/orm/gorm/app/gorm.go
generated
vendored
Normal file
72
vendor/github.com/revel/modules/orm/gorm/app/gorm.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package gormdb
|
||||
|
||||
// # Database config
|
||||
// db.driver=sqlite3 # mysql, postgres, sqlite3
|
||||
// db.host=localhost # Use dbhost /tmp/app.db is your driver is sqlite
|
||||
// db.user=dbuser
|
||||
// db.name=dbname
|
||||
// db.password=dbpassword
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql" // mysql package
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres" // postgres package
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite" // mysql package
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
// DB Gorm
|
||||
var (
|
||||
DB *gorm.DB
|
||||
gormLog = revel.AppLog
|
||||
)
|
||||
func init() {
|
||||
revel.RegisterModuleInit(func(m *revel.Module){
|
||||
gormLog = m.Log
|
||||
})
|
||||
}
|
||||
|
||||
// InitDB database
|
||||
func OpenDB(dbDriver string, dbInfo string) {
|
||||
db, err := gorm.Open(dbDriver, dbInfo)
|
||||
if err != nil {
|
||||
gormLog.Fatal("sql.Open failed", "error", err)
|
||||
}
|
||||
DB = db
|
||||
}
|
||||
|
||||
type DbInfo struct {
|
||||
DbDriver string
|
||||
DbHost string
|
||||
DbUser string
|
||||
DbPassword string
|
||||
DbName string
|
||||
}
|
||||
|
||||
func InitDBWithParameters(params DbInfo) {
|
||||
dbInfo := ""
|
||||
switch params.DbDriver {
|
||||
default:
|
||||
dbInfo = fmt.Sprintf(params.DbHost)
|
||||
case "postgres":
|
||||
dbInfo = fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable password=%s", params.DbHost, params.DbUser, params.DbName, params.DbPassword)
|
||||
case "mysql":
|
||||
dbInfo = fmt.Sprintf("%s:%s@%s/%s?charset=utf8&parseTime=True&loc=Local", params.DbUser, params.DbPassword, params.DbHost, params.DbName)
|
||||
}
|
||||
OpenDB(params.DbDriver, dbInfo)
|
||||
|
||||
}
|
||||
|
||||
func InitDB() {
|
||||
params := DbInfo{}
|
||||
params.DbDriver = revel.Config.StringDefault("db.driver", "sqlite3")
|
||||
params.DbHost = revel.Config.StringDefault("db.host", "localhost")
|
||||
if params.DbDriver == "sqlite3" && params.DbHost == "localhost" {
|
||||
params.DbHost = "/tmp/app.db"
|
||||
}
|
||||
params.DbUser = revel.Config.StringDefault("db.user", "default")
|
||||
params.DbPassword = revel.Config.StringDefault("db.password", "")
|
||||
params.DbName = revel.Config.StringDefault("db.name", "default")
|
||||
|
||||
InitDBWithParameters(params)
|
||||
}
|
||||
3
vendor/github.com/revel/modules/orm/gorm/gorm.go
generated
vendored
Normal file
3
vendor/github.com/revel/modules/orm/gorm/gorm.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package gorm
|
||||
|
||||
// Required for vendoring see golang.org/issue/13832
|
||||
264
vendor/github.com/revel/modules/orm/gorp/app/README.md
generated
vendored
Normal file
264
vendor/github.com/revel/modules/orm/gorp/app/README.md
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
modules/gorp
|
||||
===============
|
||||
|
||||
This composite orm module combines Gorp with Squirrel to give you a complete solution
|
||||
* [Gorp](https://github.com/go-gorp/gorp) *saves you time, minimizes the drudgery of
|
||||
getting data in and out of your database, and helps your code focus on algorithms,
|
||||
not infrastructure*.
|
||||
* [Squirrel](https://github.com/Masterminds/squirrel) *helps you build SQL queries from
|
||||
composable parts*
|
||||
|
||||
## Activation
|
||||
```ini
|
||||
module.gorp = github.com/revel/modules/orm/gorp
|
||||
```
|
||||
|
||||
## Drivers
|
||||
|
||||
* sqlite3
|
||||
* postgres
|
||||
* mysql
|
||||
|
||||
## Configuration file
|
||||
|
||||
```ini
|
||||
# Database config
|
||||
db.autoinit=true # default=true
|
||||
db.driver=postgres # mysql, postgres, sqlite3
|
||||
|
||||
# The database connection properties individually or use the db.connection
|
||||
db.host=localhost # Use db.host /tmp/app.db is your driver is sqlite
|
||||
db.user=dbuser
|
||||
db.name=dbname
|
||||
db.password=dbpassword
|
||||
|
||||
# Database connection string (host, user, dbname and other params)
|
||||
db.connection=localhost port=8500 user=user dbname=mydb sslmode=disable password=ack
|
||||
# If true then the database will be initialized on startup.
|
||||
db.autoinit=true
|
||||
```
|
||||
## Decelerations
|
||||
A global `Db *DbGorp` object is created in `github.com/revel/modules/gorp/app`.
|
||||
The `Db` is initialized from the app.conf if `db.autoinit=true`.
|
||||
```go
|
||||
// DB Gorp
|
||||
type DbGorp struct {
|
||||
Gorp *gorp.DbMap
|
||||
// The Sql statement builder to use to build select statements
|
||||
SqlStatementBuilder sq.StatementBuilderType
|
||||
}
|
||||
|
||||
var (
|
||||
// The database map to use to populate data
|
||||
Db = &DbGorp{}
|
||||
)
|
||||
|
||||
```
|
||||
## Usage
|
||||
If `db.autoinit=true` in app.conf then you can add your tables to Gorp on app start.
|
||||
Note that the tables are added as a function using `gorp.Db.SetDbInit` - this is for database thread pooling
|
||||
```go
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/gorp/app"
|
||||
)
|
||||
func init() {
|
||||
revel.OnAppStart(func(){
|
||||
// Register tables
|
||||
gorp.Db.SetDbInit(func(dbGorp *gorp.DbGorp) error {
|
||||
// Register tables
|
||||
gorp.Db.Map.AddTableWithName(model.MyTable{}, "my_table")
|
||||
return nil
|
||||
})
|
||||
},5)
|
||||
}
|
||||
```
|
||||
### Controller
|
||||
Controllers, with the `gorpController.Controller` embedded,
|
||||
have a gorp.DbGorp populated in the `Controller.Db`. This database is
|
||||
the global one that is created on startup
|
||||
|
||||
```go
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/orm/gorp/app/controllers"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
gorpController.Controller
|
||||
}
|
||||
type TableRow struct {
|
||||
Id int `db:"id,int64"`
|
||||
}
|
||||
func (c App) Index() revel.Result {
|
||||
sql,args,_ := c.Db.SqlStatementBuilder.Select("*").From("table").Limit(1).ToSql()
|
||||
row := &TableRow{}
|
||||
if err:= c.Db.Map.SelectOne(row,sql,args...); err!=nil {
|
||||
c.RenderError(err)
|
||||
}
|
||||
return c.Render(row)
|
||||
}
|
||||
```
|
||||
|
||||
### Multiple databases
|
||||
The gorp module can populate a `DbGorp` object for you from a `gorp.DbInfo` object. So if you don't want
|
||||
to use the global database (in the gorp module) you can initialize another anywhere in your project.
|
||||
```go
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/orm/gorp/app"
|
||||
)
|
||||
var (
|
||||
SecondDb = &gorp.DbGorp{}
|
||||
)
|
||||
func init() {
|
||||
revel.OnAppStart(func(){
|
||||
// Create a DbInfo object with a minimum of a driver and other details
|
||||
params := gorp.DbInfo{Driver:"postgres",DbUser:revel.Config.StringDefault("seconddb.user", "default")}
|
||||
secondDb.Info = params
|
||||
if err:=secondDb.InitDb(true); err!=nil {
|
||||
revel.Panicf("Second database failed to open %s", err.Error())
|
||||
}
|
||||
},0)
|
||||
}
|
||||
```
|
||||
|
||||
### Multi Channel Connections
|
||||
This is not connection pooling - this is for distributing work across multiple channels to get a
|
||||
lot of stuff done fast. It creates a bunch workers and each worker has
|
||||
its own connection (On the start of the worker a status is sent in case you want to do some prework).
|
||||
Tasks are sent through the `DbWorkContainer.InputChannel` which distributes the
|
||||
task to whatever worker is available.
|
||||
|
||||
If you are using any tables that requires GORP to have initialized tables you
|
||||
must register the tables using `gorp.Db.SetDbInit`. This is the only way that this service
|
||||
can properly initialize the newly thread created GORP instances. Here is an example.
|
||||
```go
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
"github.com/revel/modules/gorp/app"
|
||||
)
|
||||
func init() {
|
||||
revel.OnAppStart(func(){
|
||||
// Register tables
|
||||
gorp.Db.SetDbInit(func(dbGorp *gorp.DbGorp) error {
|
||||
// Register tables
|
||||
gorp.Db.Map.AddTableWithName(model.MyTable{}, "my_table")
|
||||
return nil
|
||||
})
|
||||
},5)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
In order to achieve this there is a `gorp.DbWorkerContainer` which is initialized by
|
||||
`NewDbWorker(db *DbGorp, callBack DbCallback, numWorkers int) (container *DbWorkerContainer, err error)`
|
||||
The `DbCallback` can be initialized by
|
||||
`gorp.MakeCallback(status func(phase WorkerPhase, worker *DbWorker), work func(value interface{}, worker *DbWorker)) DbCallback`
|
||||
()the status function is optional) or implemented by your structure
|
||||
|
||||
Once the `gorp.DbWorkerContainer` is created tasks can be submitted to it by using the
|
||||
`gorp.DbWorkerContainer.InputChannel<-task` this will call the `gorp.DbCallback.Work` function
|
||||
passing in an instance of *DbWorker
|
||||
|
||||
```go
|
||||
// Assume sourceDb is a *gorp.DbGorp instance
|
||||
workerPool := gorp.NewDbWorker(d.Db, gorp.MakeCallback(func(phase gorp.WorkerPhase, worker *gorp.DbWorker) {
|
||||
// On start initialize some data to be used later
|
||||
if phase == gorp.Start {
|
||||
dataList, err := model.FetchData(worker.Db)
|
||||
worker.SharedData["dataList"] = dataList
|
||||
|
||||
} else if phase == gorp.JobLongrunning {
|
||||
revel.AppLog.Error("Long running process detected", "worker", worker.Id)
|
||||
}
|
||||
}, func(work interface{}, worker *gorp.DbWorker) {
|
||||
dataList := worker.SharedData["dataList"].(model.DataList)
|
||||
// Whatever is sent into the workerPool.InputChannel<- will be the value
|
||||
value := work.(*SomeObject)
|
||||
|
||||
}), 100)
|
||||
// Set the timeout for watchdog notifications
|
||||
workerPool.LongWorkTimeout=300
|
||||
err := workerPool.Start() // Start a 100 worker threads
|
||||
if err!=nil {
|
||||
return err
|
||||
}
|
||||
defer workerPool.Close(0) // Close, wait for channels to exit (non zero would exit after timeout)
|
||||
// var tasks[] a large list of work to be done
|
||||
tasksBlock := make([]*SomeObject,100)
|
||||
for i,task := range tasks {
|
||||
if i>0 && i%100==0 {
|
||||
workerPool.InputChannel<-taskBlock
|
||||
tasksBlock = make([]*SomeObject)
|
||||
}
|
||||
taskBlock = append(taskBlock, task)
|
||||
}
|
||||
workerPool.InputChannel<-taskBlock
|
||||
// Pool is closed on defer function, it will not return till pool closes
|
||||
return nil
|
||||
```
|
||||
#### Implementation notes
|
||||
If your "work" is short but there is a lot of it then it is highly recommended you pass in lists of
|
||||
items to work on. Channels are great at providing an easy way
|
||||
to move data to and from threads but it is a process of synchronizing between two threads. If you pass
|
||||
in a single object at a time you pay that cost on every row you pass. If you do it once every 10,000
|
||||
rows then the cost is minimal.
|
||||
|
||||
#### WorkParallel function
|
||||
There is a handy function called
|
||||
`WorkParallel(db *DbGorp, tasks []func(worker *DbWorker), returnResults bool, maxNumWorkers int, timeouts int) (err error)`
|
||||
which makes it simple to do create a group of calls
|
||||
```go
|
||||
// Assume sourceDb is a *gorp.DbGorp instance
|
||||
task := func(query string) func(db *gorp.DbWorker) {
|
||||
return func(worker *gorp.DbWorker) {
|
||||
_, e := worker.Db.Map.Exec("ANALYZE " + query)
|
||||
}
|
||||
}
|
||||
gorp.WorkParallel(sourceDb, []func(worker *gorp.DbWorker){
|
||||
task("history"),
|
||||
task("summary"),
|
||||
task("daily"),
|
||||
task("monthly"),
|
||||
}, false, 0, 0)
|
||||
|
||||
```
|
||||
#### Returning data from workers
|
||||
`gorp.DbWorker` contains an OutputChannel which you can send the results back to, you must read
|
||||
from the output the same number of times that you wrote. The output size is the same size as the
|
||||
|
||||
```go
|
||||
// Assume sourceDb is a *gorp.DbGorp instance
|
||||
task := func(query string) func(db *gorp.DbWorker) {
|
||||
return func(worker *gorp.DbWorker) {
|
||||
result, err := worker.Db.Map.Exec("ANALYZE " + query)
|
||||
worker.OutputChannel <- []interface{}{result,err}
|
||||
}
|
||||
}
|
||||
r,e:=gorp.WorkParallel(sourceDb, []func(worker *gorp.DbWorker){
|
||||
task("history"),
|
||||
task("daily"),
|
||||
task("monthly"),
|
||||
},true, 0, 0)
|
||||
|
||||
println(r, e)
|
||||
for _,result := range r {
|
||||
|
||||
key,err:= result.([]interface{})[0],result.([]interface{})[1]
|
||||
fmt.Println("Returned result",key,"error",err)
|
||||
}
|
||||
|
||||
```
|
||||
#### Watchdog Timeouts
|
||||
`gorp.DbWorkerContainer` contains a couple of timeout settings (in seconds) used to monitor
|
||||
the startup and running of the workers for the duration of the container
|
||||
(this is typically called a watchdog timeout).
|
||||
- `StartWorkTimeout` If greater then 0 this is the timeout in seconds that it takes to start a worker.
|
||||
- `LongWorkTimeout` If greater then 0 this is the timeout in seconds that it takes before a
|
||||
notification is sent to the `DbCallbackImplied.StatusFn func(phase WorkerPhase, worker *DbWorker)`
|
||||
if a worker runs past X seconds on a single task.
|
||||
Each worker will have their own watchdog channel and it will send a `gorp.JobLongrunning` and
|
||||
the `gorp.DBWorker` to the status function so you can log or investigate long running processes
|
||||
69
vendor/github.com/revel/modules/orm/gorp/app/controllers/controller.go
generated
vendored
Normal file
69
vendor/github.com/revel/modules/orm/gorp/app/controllers/controller.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package gorpController
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/revel/modules/orm/gorp/app"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
// Controller definition for database transaction
|
||||
// This controller is only useful if you intend to use the database instance
|
||||
// defined in github.com/revel/modules/orm/gorp/app.Db
|
||||
type Controller struct {
|
||||
*revel.Controller
|
||||
Txn *gorp.Transaction
|
||||
Db *gorp.DbGorp
|
||||
}
|
||||
|
||||
// Begin a transaction
|
||||
func (c *Controller) Begin() revel.Result {
|
||||
c.Db = gorp.Db
|
||||
txn, err := gorp.Db.Begin()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.Txn = txn
|
||||
return nil
|
||||
}
|
||||
|
||||
// Rollback if it's still going (must have panicked).
|
||||
func (c *Controller) Rollback() revel.Result {
|
||||
if c.Txn != nil {
|
||||
if err := c.Txn.Rollback(); err != nil {
|
||||
if err != sql.ErrTxDone {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
c.Txn = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit the transaction.
|
||||
func (c *Controller) Commit() revel.Result {
|
||||
if c.Txn != nil {
|
||||
if err := c.Txn.Commit(); err != nil {
|
||||
if err != sql.ErrTxDone {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
c.Txn = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Run this as soon as possible
|
||||
revel.OnAppStart(func() {
|
||||
if revel.Config.BoolDefault("db.autoinit", false) {
|
||||
if err := gorp.InitDb(gorp.Db); err != nil {
|
||||
// Force a failure
|
||||
revel.RevelLog.Panicf("gorp:Unable to initialize database")
|
||||
}
|
||||
revel.InterceptMethod((*Controller).Begin, revel.BEFORE)
|
||||
revel.InterceptMethod((*Controller).Commit, revel.AFTER)
|
||||
revel.InterceptMethod((*Controller).Rollback, revel.FINALLY)
|
||||
}
|
||||
}, 0,
|
||||
)
|
||||
}
|
||||
168
vendor/github.com/revel/modules/orm/gorp/app/dbgorp.go
generated
vendored
Normal file
168
vendor/github.com/revel/modules/orm/gorp/app/dbgorp.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package gorp
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
sq "gopkg.in/Masterminds/squirrel.v1"
|
||||
"gopkg.in/gorp.v2"
|
||||
"github.com/revel/revel/logger"
|
||||
)
|
||||
|
||||
// DB Gorp
|
||||
type DbGorp struct {
|
||||
Map *gorp.DbMap
|
||||
// The Sql statement builder to use to build select statements
|
||||
SqlStatementBuilder sq.StatementBuilderType
|
||||
// Database connection information
|
||||
Info *DbInfo
|
||||
// The database initialization function
|
||||
dbInitFn func(dbMap *DbGorp) error
|
||||
}
|
||||
|
||||
type DbInfo struct {
|
||||
DbDriver string
|
||||
DbHost string
|
||||
DbUser string
|
||||
DbPassword string
|
||||
DbName string
|
||||
DbConnection string
|
||||
Dialect gorp.Dialect
|
||||
}
|
||||
|
||||
// OpenDb database
|
||||
func (dbGorp *DbGorp) OpenDb() (err error) {
|
||||
db, err := sql.Open(dbGorp.Info.DbDriver, dbGorp.Info.DbConnection)
|
||||
if err != nil {
|
||||
moduleLogger.Fatal("Open Database Error", "error", err)
|
||||
}
|
||||
|
||||
// Create the database map
|
||||
dbGorp.Map = &gorp.DbMap{Db: db, Dialect: dbGorp.Info.Dialect}
|
||||
|
||||
return dbGorp.dbInit()
|
||||
}
|
||||
|
||||
// Create a new database connection and open it from this one
|
||||
func (dbGorp *DbGorp) CloneDb(open bool) (newDb *DbGorp, err error) {
|
||||
dbInfo := *dbGorp.Info
|
||||
newDb = &DbGorp{Info: &dbInfo}
|
||||
newDb.dbInitFn = dbGorp.dbInitFn
|
||||
err = newDb.InitDb(open)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Close the database connection
|
||||
func (dbGorp *DbGorp) Begin() (txn *Transaction, err error) {
|
||||
tx,err := dbGorp.Map.Begin()
|
||||
if err!=nil {
|
||||
return
|
||||
}
|
||||
txn = &Transaction{tx}
|
||||
return
|
||||
}
|
||||
|
||||
// Close the database connection
|
||||
func (dbGorp *DbGorp) Close() (err error) {
|
||||
if dbGorp.Map.Db != nil {
|
||||
err = dbGorp.Map.Db.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Called to perform table registration and anything else that needs to be done on a new connection
|
||||
func (dbGorp *DbGorp) dbInit() (err error) {
|
||||
if dbGorp.dbInitFn != nil {
|
||||
err = dbGorp.dbInitFn(dbGorp)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Used to specifiy the init function to call when database is initialized
|
||||
// Calls the init function immediately
|
||||
func (dbGorp *DbGorp) SetDbInit(dbInitFn func(dbMap *DbGorp) error) (err error) {
|
||||
dbGorp.dbInitFn = dbInitFn
|
||||
return dbGorp.dbInit()
|
||||
}
|
||||
|
||||
func (dbGorp *DbGorp) Select(i interface{}, builder sq.SelectBuilder) (l []interface{}, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
list, err := dbGorp.Map.Select(i, query, args...)
|
||||
if err != nil && gorp.NonFatalError(err) {
|
||||
return list, nil
|
||||
}
|
||||
if err==sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dbGorp *DbGorp) SelectOne(i interface{}, builder sq.SelectBuilder) (err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
err = dbGorp.Map.SelectOne(i, query, args...)
|
||||
if err != nil && gorp.NonFatalError(err) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (dbGorp *DbGorp) SelectInt(builder sq.SelectBuilder) (i int64, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
i, err = dbGorp.Map.SelectInt(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (dbGorp *DbGorp) ExecUpdate(builder sq.UpdateBuilder) (r sql.Result, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
r, err = dbGorp.Map.Exec(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (dbGorp *DbGorp) ExecInsert(builder sq.InsertBuilder) (r sql.Result, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
r, err = dbGorp.Map.Exec(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//
|
||||
// Shifted some common functions up a level
|
||||
////
|
||||
|
||||
|
||||
func (dbGorp *DbGorp) Insert(list ...interface{}) error {
|
||||
return dbGorp.Map.Insert(list...)
|
||||
}
|
||||
|
||||
func (dbGorp *DbGorp) Update(list ...interface{}) (int64, error) {
|
||||
return dbGorp.Map.Update(list...)
|
||||
}
|
||||
func (dbGorp *DbGorp) Get(i interface{}, keys ...interface{}) (interface{}, error) {
|
||||
return dbGorp.Map.Get(i,keys...)
|
||||
}
|
||||
func (dbGorp *DbGorp) Delete(i ...interface{}) (int64, error) {
|
||||
return dbGorp.Map.Delete(i...)
|
||||
}
|
||||
|
||||
func (dbGorp *DbGorp) TraceOn(log logger.MultiLogger) {
|
||||
dbGorp.Map.TraceOn("",&simpleTrace{log.New("section","gorp")})
|
||||
|
||||
}
|
||||
func (dbGorp *DbGorp) TraceOff() {
|
||||
|
||||
}
|
||||
|
||||
type simpleTrace struct {
|
||||
log logger.MultiLogger
|
||||
}
|
||||
|
||||
func (s *simpleTrace) Printf(format string, v ...interface{}) {
|
||||
s.log.Infof(format,v...)
|
||||
}
|
||||
70
vendor/github.com/revel/modules/orm/gorp/app/init_db.go
generated
vendored
Normal file
70
vendor/github.com/revel/modules/orm/gorp/app/init_db.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package gorp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql" // mysql package
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres" // postgres package
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite" // mysql package
|
||||
"github.com/revel/revel"
|
||||
sq "gopkg.in/Masterminds/squirrel.v1"
|
||||
"gopkg.in/gorp.v2"
|
||||
"github.com/revel/revel/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
// The database map to use to populate data
|
||||
Db = &DbGorp{}
|
||||
moduleLogger logger.MultiLogger
|
||||
)
|
||||
func init() {
|
||||
revel.RegisterModuleInit(func(module *revel.Module){
|
||||
moduleLogger = module.Log
|
||||
moduleLogger.Debug("Assigned Logger")
|
||||
})
|
||||
}
|
||||
func (dbResult *DbGorp)InitDb(open bool) (err error) {
|
||||
dbInfo := dbResult.Info
|
||||
|
||||
switch dbInfo.DbDriver {
|
||||
default:
|
||||
dbResult.SqlStatementBuilder = sq.StatementBuilder.PlaceholderFormat(sq.Question)
|
||||
dbInfo.Dialect = gorp.SqliteDialect{}
|
||||
if len(dbInfo.DbConnection) == 0 {
|
||||
dbInfo.DbConnection = fmt.Sprintf(dbInfo.DbHost)
|
||||
}
|
||||
case "postgres":
|
||||
dbResult.SqlStatementBuilder = sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||
dbInfo.Dialect = gorp.PostgresDialect{}
|
||||
if len(dbInfo.DbConnection) == 0 {
|
||||
dbInfo.DbConnection = fmt.Sprintf("host=%s port=8500 user=%s dbname=%s sslmode=disable password=%s", dbInfo.DbHost, dbInfo.DbUser, dbInfo.DbName, dbInfo.DbPassword)
|
||||
}
|
||||
case "mysql":
|
||||
dbResult.SqlStatementBuilder = sq.StatementBuilder.PlaceholderFormat(sq.Question)
|
||||
dbInfo.Dialect = gorp.MySQLDialect{}
|
||||
if len(dbInfo.DbConnection) == 0 {
|
||||
dbInfo.DbConnection = fmt.Sprintf("%s:%s@%s/%s?charset=utf8&parseTime=True&loc=Local", dbInfo.DbUser, dbInfo.DbPassword, dbInfo.DbHost, dbInfo.DbName)
|
||||
}
|
||||
}
|
||||
|
||||
if open {
|
||||
err = dbResult.OpenDb()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Initialize the database from revel.Config
|
||||
func InitDb(dbResult *DbGorp) (error) {
|
||||
params := DbInfo{}
|
||||
params.DbDriver = revel.Config.StringDefault("db.driver", "sqlite3")
|
||||
params.DbHost = revel.Config.StringDefault("db.host", "localhost")
|
||||
if params.DbDriver == "sqlite3" && params.DbHost == "localhost" {
|
||||
params.DbHost = "/tmp/app.db"
|
||||
}
|
||||
params.DbUser = revel.Config.StringDefault("db.user", "default")
|
||||
params.DbPassword = revel.Config.StringDefault("db.password", "")
|
||||
params.DbName = revel.Config.StringDefault("db.name", "default")
|
||||
params.DbConnection = revel.Config.StringDefault("db.connection", "")
|
||||
dbResult.Info = ¶ms
|
||||
|
||||
return dbResult.InitDb(true)
|
||||
}
|
||||
82
vendor/github.com/revel/modules/orm/gorp/app/transaction.go
generated
vendored
Normal file
82
vendor/github.com/revel/modules/orm/gorp/app/transaction.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package gorp
|
||||
import (
|
||||
gorpa "gopkg.in/gorp.v2"
|
||||
"database/sql"
|
||||
sq "gopkg.in/Masterminds/squirrel.v1"
|
||||
)
|
||||
type (
|
||||
// This is a small wrapped around gorp.Transaction so you can make use of the builder statements as well
|
||||
Transaction struct {
|
||||
Map *gorpa.Transaction
|
||||
}
|
||||
)
|
||||
|
||||
func (txn *Transaction) Rollback() (err error) {
|
||||
return txn.Map.Rollback()
|
||||
}
|
||||
func (txn *Transaction) Commit() (err error) {
|
||||
return txn.Map.Commit()
|
||||
}
|
||||
func (txn *Transaction) Select(i interface{}, builder sq.SelectBuilder) (l []interface{}, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
list, err := txn.Map.Select(i, query, args...)
|
||||
if err != nil && gorpa.NonFatalError(err) {
|
||||
return list, nil
|
||||
}
|
||||
if err==sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (txn *Transaction) SelectOne(i interface{}, builder sq.SelectBuilder) (err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
err = txn.Map.SelectOne(i, query, args...)
|
||||
if err != nil && gorpa.NonFatalError(err) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (txn *Transaction) SelectInt(builder sq.SelectBuilder) (i int64, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
i, err = txn.Map.SelectInt(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (txn *Transaction) ExecUpdate(builder sq.UpdateBuilder) (r sql.Result, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
r, err = txn.Map.Exec(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (txn *Transaction) ExecInsert(builder sq.InsertBuilder) (r sql.Result, err error) {
|
||||
query, args, err := builder.ToSql()
|
||||
if err == nil {
|
||||
r, err = txn.Map.Exec(query, args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Shifted some common functions up a level
|
||||
|
||||
func (txn *Transaction) Insert(list ...interface{}) error {
|
||||
return txn.Map.Insert(list...)
|
||||
}
|
||||
func (txn *Transaction) Update(list ...interface{}) (int64, error) {
|
||||
return txn.Map.Update(list...)
|
||||
}
|
||||
func (txn *Transaction) Get(i interface{}, keys ...interface{}) (interface{}, error) {
|
||||
return txn.Map.Get(i,keys...)
|
||||
}
|
||||
func (txn *Transaction) Delete(i ...interface{}) (int64, error) {
|
||||
return txn.Map.Delete(i...)
|
||||
}
|
||||
268
vendor/github.com/revel/modules/orm/gorp/app/workers.go
generated
vendored
Normal file
268
vendor/github.com/revel/modules/orm/gorp/app/workers.go
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
package gorp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// The worker container
|
||||
type DbWorkerContainer struct {
|
||||
SharedWorker
|
||||
mutex sync.Mutex
|
||||
Workers []*DbWorker
|
||||
NumWorkers int
|
||||
LongWorkTimeout int64
|
||||
StartWorkTimeout int64
|
||||
Db *DbGorp
|
||||
}
|
||||
|
||||
// The timeoutInfo for monitoring long running processes
|
||||
type timeoutInfo struct {
|
||||
worker *DbWorker
|
||||
started time.Time
|
||||
ended time.Time
|
||||
state WorkerPhase
|
||||
}
|
||||
type DbWorker struct {
|
||||
Id int
|
||||
Db *DbGorp
|
||||
SharedWorker
|
||||
WorkUnit int
|
||||
SharedData map[string]interface{}
|
||||
TimeInfo *timeoutInfo
|
||||
TimeoutChannel chan *timeoutInfo
|
||||
}
|
||||
type SharedWorker struct {
|
||||
workInfo DbWorkInfo
|
||||
InputChannel chan interface{}
|
||||
OutputChannel chan interface{}
|
||||
ControlChannel chan func() (WorkerPhase, *DbWorker)
|
||||
}
|
||||
type DbWorkInfo interface {
|
||||
Status(phase WorkerPhase, worker *DbWorker)
|
||||
Work(value interface{}, worker *DbWorker)
|
||||
}
|
||||
type DbCallbackImplied struct {
|
||||
StatusFn func(phase WorkerPhase, worker *DbWorker)
|
||||
WorkFn func(value interface{}, worker *DbWorker)
|
||||
}
|
||||
type WorkerPhase int
|
||||
|
||||
const (
|
||||
Start WorkerPhase = iota
|
||||
Stop
|
||||
StartJob
|
||||
EndJob
|
||||
JobLongrunning
|
||||
)
|
||||
// Creates a container to run the group of workers (up to a max of maxNumWorkers), does not return to all workers are completed)
|
||||
// If returnResults is true then the task MUST write to the DbWorker.OutputChannel once for every task
|
||||
func WorkParallel(db *DbGorp, tasks []func(worker *DbWorker), returnResults bool, maxNumWorkers int, timeouts int) (results []interface{}, err error) {
|
||||
if maxNumWorkers == 0 {
|
||||
maxNumWorkers = len(tasks)
|
||||
}
|
||||
|
||||
// Create a container with no status callback
|
||||
container := NewDbWorker(db,
|
||||
MakeCallback(nil,
|
||||
func(value interface{}, worker *DbWorker) {
|
||||
task := value.(func(worker *DbWorker))
|
||||
task(worker)
|
||||
}), maxNumWorkers)
|
||||
err = container.Start()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, task := range tasks {
|
||||
container.InputChannel <- task
|
||||
}
|
||||
if returnResults {
|
||||
for range tasks {
|
||||
result := <-container.OutputChannel
|
||||
results = append(results, result)
|
||||
}
|
||||
}
|
||||
|
||||
container.Close(timeouts)
|
||||
return
|
||||
}
|
||||
|
||||
// This creates a DbWorkerContainer with the number of working threads already started.
|
||||
// Each working thread has their own database instance running.
|
||||
func NewDbWorker(db *DbGorp, workInfo DbWorkInfo, numWorkers int) (container *DbWorkerContainer) {
|
||||
|
||||
container = &DbWorkerContainer{
|
||||
SharedWorker: SharedWorker{
|
||||
InputChannel: make(chan interface{}, numWorkers),
|
||||
OutputChannel: make(chan interface{}, numWorkers),
|
||||
ControlChannel: make(chan func() (WorkerPhase, *DbWorker), numWorkers),
|
||||
workInfo: workInfo,
|
||||
},
|
||||
NumWorkers: numWorkers,
|
||||
Db: db,
|
||||
StartWorkTimeout: 0,
|
||||
LongWorkTimeout: 0,
|
||||
}
|
||||
return
|
||||
}
|
||||
func (container *DbWorkerContainer) Start() (err error) {
|
||||
for x := 0; x < container.NumWorkers; x++ {
|
||||
go startWorker(container, container.Db, x)
|
||||
}
|
||||
// Make sure all containers are running before returning
|
||||
for x := 0; x < container.NumWorkers; x++ {
|
||||
if container.StartWorkTimeout > 0 {
|
||||
select {
|
||||
case result := <-container.ControlChannel:
|
||||
state, source := result()
|
||||
if state != Start {
|
||||
container.Close(5)
|
||||
err = fmt.Errorf("Failed to start workers %d", source)
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Second * time.Duration(container.StartWorkTimeout)):
|
||||
container.Close(5)
|
||||
err = fmt.Errorf("Failed to start worker timeout")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
result := <-container.ControlChannel
|
||||
state, source := result()
|
||||
if state != Start {
|
||||
container.Close(5)
|
||||
err = fmt.Errorf("Failed to start workers %d", source)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (container *DbWorkerContainer) Close(timeouts int) (totalWork int, err error) {
|
||||
close(container.InputChannel)
|
||||
for x := 0; x < len(container.Workers); x++ {
|
||||
// Allow close to continue even if a worker does not respond
|
||||
if timeouts > 0 {
|
||||
select {
|
||||
case result := <-container.ControlChannel:
|
||||
_, worker := result()
|
||||
totalWork += worker.WorkUnit
|
||||
case <-time.After(time.Second * time.Duration(timeouts)):
|
||||
}
|
||||
} else {
|
||||
_, worker := (<-container.ControlChannel)()
|
||||
totalWork += worker.WorkUnit
|
||||
}
|
||||
}
|
||||
close(container.OutputChannel)
|
||||
return
|
||||
}
|
||||
|
||||
// Called by using "go" to invoke, creates a DBWorker, and starts a watchdog channel
|
||||
func startWorker(container *DbWorkerContainer, db *DbGorp, id int) {
|
||||
newDb, _ := db.CloneDb(true)
|
||||
worker := &DbWorker{
|
||||
Db: newDb,
|
||||
Id: id,
|
||||
SharedData: map[string]interface{}{},
|
||||
SharedWorker: SharedWorker{
|
||||
workInfo: container.workInfo,
|
||||
InputChannel: container.InputChannel,
|
||||
OutputChannel: container.OutputChannel,
|
||||
ControlChannel: container.ControlChannel,
|
||||
},
|
||||
}
|
||||
// Close the database after worker has ended (Start returned
|
||||
defer worker.Db.Close()
|
||||
container.mutex.Lock()
|
||||
container.Workers = append(container.Workers, worker)
|
||||
container.mutex.Unlock()
|
||||
// Only monitor jobs if Status function defined and a timeout is also defined
|
||||
if worker.workInfo.Status != nil && container.LongWorkTimeout > 0 {
|
||||
worker.TimeoutChannel = make(chan *timeoutInfo)
|
||||
go worker.TimeInfo.start(worker.TimeoutChannel, container.LongWorkTimeout)
|
||||
}
|
||||
worker.start()
|
||||
}
|
||||
|
||||
// Starts the worker, continues running until inputchannel is closed
|
||||
func (worker *DbWorker) start() {
|
||||
if worker.workInfo.Status != nil {
|
||||
worker.workInfo.Status(Start, worker)
|
||||
}
|
||||
worker.ControlChannel <- func() (WorkerPhase, *DbWorker) { return Start, worker }
|
||||
for job := range worker.InputChannel {
|
||||
worker.invoke(job)
|
||||
}
|
||||
if worker.workInfo.Status != nil {
|
||||
worker.workInfo.Status(Stop, worker)
|
||||
}
|
||||
worker.ControlChannel <- func() (WorkerPhase, *DbWorker) { return Stop, worker }
|
||||
if worker.TimeoutChannel != nil {
|
||||
close(worker.TimeoutChannel)
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper to prevent panics from disturbing the channel
|
||||
func (worker *DbWorker) invoke(job interface{}) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
trace := make([]byte, 1024)
|
||||
count := runtime.Stack(trace, true)
|
||||
moduleLogger.Error("Recover from panic: ", "error", err)
|
||||
moduleLogger.Error("Stack", "size", count, "trace", string(trace))
|
||||
}
|
||||
}()
|
||||
// Setup the timeout information
|
||||
if worker.TimeoutChannel != nil {
|
||||
worker.TimeInfo = &timeoutInfo{worker: worker, started: time.Now(), state: StartJob}
|
||||
worker.TimeoutChannel <- worker.TimeInfo
|
||||
}
|
||||
worker.workInfo.Work(job, worker)
|
||||
if worker.TimeoutChannel != nil {
|
||||
worker.TimeInfo.state = EndJob
|
||||
worker.TimeoutChannel <- worker.TimeInfo
|
||||
}
|
||||
}
|
||||
|
||||
// A function to return an object that is a valid DbCallback
|
||||
func MakeCallback(status func(phase WorkerPhase, worker *DbWorker), work func(value interface{}, worker *DbWorker)) DbWorkInfo {
|
||||
return &DbCallbackImplied{StatusFn: status, WorkFn: work}
|
||||
}
|
||||
|
||||
// Call the status function if available
|
||||
func (dbCallback *DbCallbackImplied) Status(phase WorkerPhase, worker *DbWorker) {
|
||||
if dbCallback.StatusFn != nil {
|
||||
dbCallback.StatusFn(phase, worker)
|
||||
}
|
||||
}
|
||||
|
||||
// Calls the work function
|
||||
func (dbCallback *DbCallbackImplied) Work(value interface{}, worker *DbWorker) {
|
||||
dbCallback.WorkFn(value, worker)
|
||||
}
|
||||
|
||||
//Starts the timeout worker
|
||||
func (_ *timeoutInfo) start(TimeoutChannel chan *timeoutInfo, timeout int64) {
|
||||
for j := range TimeoutChannel {
|
||||
j.started = time.Now()
|
||||
j.state = StartJob
|
||||
j.worker.workInfo.Status(j.state, j.worker)
|
||||
for {
|
||||
select {
|
||||
case complete, ok := <-TimeoutChannel:
|
||||
if !ok {
|
||||
// Channel closed returning...
|
||||
return
|
||||
}
|
||||
// Received new State, record and loop
|
||||
complete.worker.workInfo.Status(complete.state, complete.worker)
|
||||
break
|
||||
case <-time.After(time.Second * time.Duration(timeout)):
|
||||
j.worker.workInfo.Status(JobLongrunning, j.worker)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
vendor/github.com/revel/modules/orm/gorp/gorp.go
generated
vendored
Normal file
3
vendor/github.com/revel/modules/orm/gorp/gorp.go
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
package gorp
|
||||
|
||||
// Required for vendoring see golang.org/issue/13832
|
||||
Reference in New Issue
Block a user