github.com/scraniel/migrate@v0.0.0-20230320185700-339088f36cee/database/util.go (about)

     1  package database
     2  
     3  import (
     4  	"fmt"
     5  	"go.uber.org/atomic"
     6  	"hash/crc32"
     7  	"strings"
     8  )
     9  
    10  const advisoryLockIDSalt uint = 1486364155
    11  
    12  // GenerateAdvisoryLockId inspired by rails migrations, see https://goo.gl/8o9bCT
    13  func GenerateAdvisoryLockId(databaseName string, additionalNames ...string) (string, error) { // nolint: golint
    14  	if len(additionalNames) > 0 {
    15  		databaseName = strings.Join(append(additionalNames, databaseName), "\x00")
    16  	}
    17  	sum := crc32.ChecksumIEEE([]byte(databaseName))
    18  	sum = sum * uint32(advisoryLockIDSalt)
    19  	return fmt.Sprint(sum), nil
    20  }
    21  
    22  // CasRestoreOnErr CAS wrapper to automatically restore the lock state on error
    23  func CasRestoreOnErr(lock *atomic.Bool, o, n bool, casErr error, f func() error) error {
    24  	if !lock.CAS(o, n) {
    25  		return casErr
    26  	}
    27  	if err := f(); err != nil {
    28  		// Automatically unlock/lock on error
    29  		lock.Store(o)
    30  		return err
    31  	}
    32  	return nil
    33  }