63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package gorm
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
//define callbacks to reconnect in case of failure
|
|
func init() {
|
|
DefaultCallback.Create().After("gorm:create").Register("gorm:begin_reconnect", performReconnect)
|
|
DefaultCallback.Update().After("gorm:update").Register("gorm:begin_reconnect", performReconnect)
|
|
DefaultCallback.Delete().After("gorm:delete").Register("gorm:begin_reconnect", performReconnect)
|
|
DefaultCallback.Query().After("gorm:query").Register("gorm:begin_reconnect", performReconnect)
|
|
}
|
|
|
|
//May be do some kind of settings?
|
|
const reconnectAttempts = 5
|
|
const reconnectInterval = 5 * time.Second
|
|
|
|
//performReconnect the callback used to peform some reconnect attempts in case of disconnect
|
|
func performReconnect(scope *Scope) {
|
|
if scope.HasError() {
|
|
|
|
scope.db.reconnectGuard.Add(1)
|
|
defer scope.db.reconnectGuard.Done()
|
|
|
|
err := scope.db.Error
|
|
|
|
if scope.db.dialect.IsDisconnectError(err) {
|
|
for i := 0; i < reconnectAttempts; i++ {
|
|
newDb, openErr := Open(scope.db.dialectName, scope.db.dialectArgs...)
|
|
if openErr == nil {
|
|
oldDb := scope.db
|
|
if oldDb.parent != oldDb {
|
|
//In case of cloned db try to fix parents
|
|
//It is thread safe as we share mutex between instances
|
|
fixParentDbs(oldDb, newDb)
|
|
}
|
|
*scope.db = *newDb
|
|
break
|
|
} else {
|
|
//wait for interval and try to reconnect again
|
|
<-time.After(reconnectInterval)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func fixParentDbs(current, newDb *DB) {
|
|
iterator := current
|
|
parent := current.parent
|
|
|
|
for {
|
|
oldParent := parent
|
|
*parent = *newDb
|
|
parent = oldParent.parent
|
|
iterator = oldParent
|
|
if iterator == parent {
|
|
break
|
|
}
|
|
}
|
|
}
|