Permalink
Browse files

Remove sql.Tx from Controller

Convert db filter to a mixin.  Controllers that want to use a sql.Tx
can mix-in db.Transactional
  • Loading branch information...
1 parent a65fc98 commit 323ee819c57cd2c726e7170b0cf6ccea7ce4dea7 @robfig committed May 25, 2013
Showing with 35 additions and 18 deletions.
  1. +0 −2 controller.go
  2. +35 −16 modules/db/app/db.go
View
2 controller.go
@@ -1,7 +1,6 @@
package revel
import (
- "database/sql"
"errors"
"fmt"
"net/http"
@@ -31,7 +30,6 @@ type Controller struct {
Args map[string]interface{} // Per-request scratch space.
RenderArgs map[string]interface{} // Args passed to the template.
Validation *Validation // Data validation helpers
- Txn *sql.Tx // Nil by default, but may be used by the app / plugins
}
func NewController(req *Request, resp *Response) *Controller {
View
51 modules/db/app/db.go
@@ -1,7 +1,12 @@
-// This plugin provides a database transaction to the application.
-// A transaction is begun before each request and committed on success.
-// If a panic occurred during the request, the transaction is rolled back.
-// (The application may also roll the transaction back itself.)
+// This module configures a database connection for the application.
+//
+// Developers use this module by importing and calling db.Init().
+// A "Transactional" controller type is provided as a way to import interceptors
+// that manage the transaction
+//
+// In particular, a transaction is begun before each request and committed on
+// success. If a panic occurred during the request, the transaction is rolled
+// back. (The application may also roll the transaction back itself.)
package db
import (
@@ -33,30 +38,44 @@ func Init() {
}
}
-var DbFilter = func(c *revel.Controller, fc []revel.Filter) {
- // Begin transaction
+type Transactional struct {
+ *revel.Controller
+ Txn *sql.Tx
+}
+
+// Begin a transaction
+func (c Transactional) Begin() revel.Result {
txn, err := Db.Begin()
if err != nil {
panic(err)
}
c.Txn = txn
+ return nil
+}
- // Catch panics and roll back.
- defer func() {
- if err := c.Txn.Rollback(); err != nil {
- if err != sql.ErrTxDone {
- panic(err)
- }
+// Rollback if it's still going (must have panicked).
+func (c Transactional) Rollback() revel.Result {
+ if err := c.Txn.Rollback(); err != nil {
+ if err != sql.ErrTxDone {
+ panic(err)
}
- }()
-
- fc[0](c, fc[1:])
+ }
+ return nil
+}
- // Commit
+// Commit the transaction.
+func (c Transactional) Commit() revel.Result {
if err := c.Txn.Commit(); err != nil {
if err != sql.ErrTxDone {
panic(err)
}
}
c.Txn = nil
+ return nil
+}
+
+func init() {
+ revel.InterceptMethod(Transactional.Begin, revel.BEFORE)
+ revel.InterceptMethod(Transactional.Commit, revel.AFTER)
+ revel.InterceptMethod(Transactional.Rollback, revel.FINALLY)
}

0 comments on commit 323ee81

Please sign in to comment.