Skip to content

Instantly share code, notes, and snippets.

@excavador
Created September 4, 2018 13:08
Show Gist options
  • Save excavador/e0da2ee133f044a741219d191c6b83f8 to your computer and use it in GitHub Desktop.
Save excavador/e0da2ee133f044a741219d191c6b83f8 to your computer and use it in GitHub Desktop.
func Temporary(err error) bool {
switch err.(type) {
case net.Error:
return err.(net.Error).Temporary()
}
if err, ok := err.(*pq.Error); ok {
code := err.Code
switch code.Class() {
case "00": // Successful Completion
case "01": // Warning
case "02": // No Data (this is also a warning class per the SQL standard)
case "03": // SQL Statement Not Yet Done
case "08": // Connection Exception
return true
case "40": // Transaction Rollback
// deadlock_detected
if string(code) == "40P01" {
return true
}
// could not serialize access due to concurrent update
if string(code) == "40001" {
return true
}
}
}
return false
}
func (db *db) Db(ctx context.Context, action action) (err error) {
for {
// try to perform the action
...
if err = action(ctx, session); err == nil {
return
} else if Temporary(err) {
logger.Debugf(ctx, "temporary problem %s", err)
select {
// check for cancel
case <-ctx.Done():
err = ctx.Err()
logger.Errorf(ctx, "canceled %s", err)
return
// TODO: Randomize timeout a little?
// wait retry interval
case <-time.After(time.Duration(db.cfgRetryInterval)):
logger.Debugf(ctx, "repeat")
}
} else {
return
}
}
}
func UseMagicLink(ctx context.Context, token string) (username string, err error) {
action := func(ctx context.Context, tx *sql.Tx) (err error) {
err = db.Get(ctx, tx, db.JSONB(&username),
"SELECT func.get_magic_link($1)", token)
if err != nil {
logger.Errorf(ctx, "problem: %s", err)
}
return
}
err = ctx.Value("db").(db.DB).Tx(ctx, action)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment