Skip to content
Snippets Groups Projects
Select Git revision
  • 833fb0c521956c4ff381129c13052c8524838617
  • master default protected
  • Jakub/rootless-CI
  • xx-4078/defaults
  • hotfix/nullableStake
  • november-commitments
  • new-cli
  • dev
  • jonah/rest
  • jonah/cli
  • v1.0-cli
11 results

database.go

Blame
  • database.go 3.87 KiB
    ///////////////////////////////////////////////////////////////////////////////
    // Copyright © 2021 xx network SEZC                                          //
    //                                                                           //
    // Use of this source code is governed by a license that can be found in the //
    // LICENSE file                                                              //
    ///////////////////////////////////////////////////////////////////////////////
    
    package storage
    
    import (
    	"fmt"
    	"github.com/pkg/errors"
    	jww "github.com/spf13/jwalterweatherman"
    	"gorm.io/driver/postgres"
    	"gorm.io/gorm"
    	"gorm.io/gorm/logger"
    	"time"
    )
    
    type database interface {
    	InsertMembers([]Member) error
    	InsertCommitment(Commitment) error
    
    	GetMember(hexID string) (*Member, error)
    	GetCommitment(id string) (*Commitment, error)
    }
    
    // DatabaseImpl struct implements the Database Interface with an underlying DB
    type DatabaseImpl struct {
    	db *gorm.DB // Stored database connection
    }
    
    type Member struct {
    	Id   []byte `gorm:"primary_key"`
    	Cert []byte `gorm:"NOT NULL"`
    }
    
    type Commitment struct {
    	Id              []byte `gorm:"primary_key"`
    	Contract        []byte `gorm:"not null"`
    	Wallet          string `gorm:"not null"`
    	NominatorWallet string
    	Email           string
    	Signature       []byte `gorm:"not null"`
    	SelectedStake   int
    	MaxStake        int `gorm:"default:137068"`
    	CreatedAt       time.Time
    }
    
    // newDatabase initializes the database interface with either Database or Map backend
    // Returns a database interface and error
    func newDatabase(username, password, dbName, address,
    	port string) (database, error) {
    
    	var err error
    	var db *gorm.DB
    	// Connect to the database if the correct information is provided
    	if address != "" && port != "" {
    		// Create the database connection
    		connectString := fmt.Sprintf(
    			"host=%s port=%s user=%s dbname=%s sslmode=disable",
    			address, port, username, dbName)
    		// Handle empty database password
    		if len(password) > 0 {
    			connectString += fmt.Sprintf(" password=%s", password)
    		}
    		db, err = gorm.Open(postgres.Open(connectString), &gorm.Config{
    			Logger: logger.New(jww.TRACE, logger.Config{LogLevel: logger.Info}),
    		})
    	}
    
    	// Return the map-backend interface
    	// in the event there is a database error or information is not provided
    	if (address == "" || port == "") || err != nil {
    
    		var failReason string
    		if err != nil {
    			failReason = fmt.Sprintf("Unable to initialize database backend: %+v", err)
    			jww.WARN.Printf(failReason)
    		} else {
    			failReason = "Database backend connection information not provided"
    			jww.WARN.Printf(failReason)
    		}
    
    		defer jww.INFO.Println("Map backend initialized successfully!")
    
    		mapImpl := &MapImpl{
    			members:     map[string]Member{},
    			commitments: map[string]Commitment{},
    		}
    
    		return database(mapImpl), nil
    	}
    
    	// Get and configure the internal database ConnPool
    	sqlDb, err := db.DB()
    	if err != nil {
    		return database(&DatabaseImpl{}), errors.Errorf("Unable to configure database connection pool: %+v", err)
    	}
    	// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
    	sqlDb.SetMaxIdleConns(10)
    	// SetMaxOpenConns sets the maximum number of open connections to the Database.
    	sqlDb.SetMaxOpenConns(50)
    	// SetConnMaxLifetime sets the maximum amount of time a connection may be idle.
    	sqlDb.SetConnMaxIdleTime(10 * time.Minute)
    	// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
    	sqlDb.SetConnMaxLifetime(12 * time.Hour)
    
    	// Initialize the database schema
    	// WARNING: Order is important. Do not change without database testing
    	models := []interface{}{Member{}, Commitment{}}
    	for _, model := range models {
    		err = db.AutoMigrate(model)
    		if err != nil {
    			return database(&DatabaseImpl{}), err
    		}
    	}
    
    	// Build the interface
    	di := &DatabaseImpl{
    		db: db,
    	}
    
    	jww.INFO.Println("Database backend initialized successfully!")
    	return database(di), nil
    }