Skip to content

Instantly share code, notes, and snippets.

@ota42y
Created April 4, 2020 05:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ota42y/06c4e72f35e7aead7e14819a62b8cfbf to your computer and use it in GitHub Desktop.
Save ota42y/06c4e72f35e7aead7e14819a62b8cfbf to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math/rand"
"time"
"github.com/DATA-DOG/go-txdb"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres" // Use PostgreSQL in gorm
)
func main() {
dial := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s&statement_timeout=2000", "gorm", "gorm", "localhost", "15432", "test1", "disable")
{
conn, err := gorm.Open("postgres", dial)
if err != nil {
panic(err)
}
conn.AutoMigrate(&User{})
if err := conn.Close(); err != nil {
panic(err)
}
}
{
name := RandStringRunes(100)
conn1, err := gorm.Open("postgres", dial)
if err != nil {
panic(err)
}
conn2, err := gorm.Open("postgres", dial)
if err != nil {
panic(err)
}
err = testExec(conn1, conn2, name)
fmt.Println(err)
if err := conn1.Close(); err != nil {
panic(err)
}
if err := conn2.Close(); err != nil {
panic(err)
}
}
fmt.Println("conn3, conn4")
{
name := RandStringRunes(100)
conn3, err := gorm.Open("postgres", dial)
if err != nil {
panic(err)
}
conn4, err := gorm.Open("postgres", dial)
if err != nil {
panic(err)
}
conn3 = conn3.Begin()
conn4 = conn4.Begin()
err = testExec(conn3, conn4, name) // conn3 wait lock so we got timeout error
fmt.Println(err)
if err := conn3.Rollback().Error; err != nil {
panic(err)
}
if err := conn4.Rollback().Error; err != nil {
panic(err)
}
if err := conn3.Close(); err != nil {
panic(err)
}
if err := conn4.Close(); err != nil {
panic(err)
}
}
fmt.Println("txdb")
{
dbname := "postgreql_txdb"
txdb.Register(dbname, "postgres", dial)
dialect, ok := gorm.GetDialect("postgres")
if !ok {
panic(fmt.Errorf("dialect not exist"))
}
gorm.RegisterDialect(dbname, dialect)
name := RandStringRunes(100)
conn5, err := gorm.Open(dbname, "conn1")
if err != nil {
panic(err)
}
conn6, err := gorm.Open(dbname, "conn2")
if err != nil {
panic(err)
}
err = testExec(conn5, conn6, name)
fmt.Println(err) // timeout
if err := conn5.Close(); err != nil {
panic(err)
}
if err := conn6.Close(); err != nil {
panic(err)
}
}
fmt.Println("end")
}
func testExec(conn1 *gorm.DB, conn2 *gorm.DB, name string) error {
err := conn1.Save(&User{Name: name}).Error
if err != nil {
panic(err) // should be always succeed
}
err = conn2.Save(&User{Name: name}).Error
if err != nil {
fmt.Println("save failed")
return err
}
return nil
}
// https://stackoverflow.com/questions/22892120/how-to-generate-a-random-string-of-a-fixed-length-in-go
func init() {
rand.Seed(time.Now().UnixNano())
}
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func RandStringRunes(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
type User struct {
gorm.Model
Name string `json:"name" gorm:"unique;not null"`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment