status-go/protocol/storenodes/storenodes.go
Pablo Lopez 3f19972c8e
enable custom community storenodes (#4532)
* enable custom community store nodes

* fix

* fix

* fix

* fix

* cleanup

* fix

* migration

* fix

* cleanup

* fix

* cleanup

* fix

* fix

* cleanup

* message to update the community storenodes

* rename

* fix test

* wait for availability only if global storenode

* fix test

* fix typo

* sync community storenodes

* remove unused

* add tests

* fix imports

* fix todo

* unused

* pr comments

* pr feedback

* revert merge deleted

* fix lint

* fix db and perform ms request

* typo

* fix log

* fix go imports

* refactor handle message

* cleanup public message

* add tests

* fix test

* cleanup test

* fix test

* avoid making one file to big to keep codeclimate from complaining

* fix lint

* revert

* Update protocol/storenodes/database.go

Co-authored-by: richΛrd <info@richardramos.me>

* Update protocol/messenger_mailserver_cycle.go

Co-authored-by: richΛrd <info@richardramos.me>

* PR comment

* fix tx

* proto files

* pr comment

---------

Co-authored-by: richΛrd <info@richardramos.me>
2024-02-20 17:49:39 +02:00

115 lines
3.3 KiB
Go

package storenodes
import (
"errors"
"sync"
"go.uber.org/zap"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/services/mailservers"
)
var (
ErrNotFound = errors.New("not found")
)
// CommunityStorenodes has methods to handle the storenodes for a community
type CommunityStorenodes struct {
storenodesByCommunityIDMutex *sync.RWMutex
storenodesByCommunityID map[string]storenodesData
storenodesDB *Database
logger *zap.Logger
}
func NewCommunityStorenodes(storenodesDB *Database, logger *zap.Logger) *CommunityStorenodes {
if logger == nil {
logger = zap.NewNop()
}
return &CommunityStorenodes{
storenodesByCommunityIDMutex: &sync.RWMutex{},
storenodesByCommunityID: make(map[string]storenodesData),
storenodesDB: storenodesDB,
logger: logger.With(zap.Namespace("CommunityStorenodes")),
}
}
type storenodesData struct {
storenodes []Storenode
}
// GetStorenodeByCommunnityID returns the active storenode for a community
func (m *CommunityStorenodes) GetStorenodeByCommunnityID(communityID string) (mailservers.Mailserver, error) {
m.storenodesByCommunityIDMutex.RLock()
defer m.storenodesByCommunityIDMutex.RUnlock()
msData, ok := m.storenodesByCommunityID[communityID]
if !ok || len(msData.storenodes) == 0 {
return mailservers.Mailserver{}, ErrNotFound
}
return toMailserver(msData.storenodes[0]), nil
}
func (m *CommunityStorenodes) IsCommunityStoreNode(id string) bool {
m.storenodesByCommunityIDMutex.RLock()
defer m.storenodesByCommunityIDMutex.RUnlock()
for _, data := range m.storenodesByCommunityID {
for _, snode := range data.storenodes {
if snode.StorenodeID == id {
return true
}
}
}
return false
}
func (m *CommunityStorenodes) HasStorenodeSetup(communityID string) bool {
m.storenodesByCommunityIDMutex.RLock()
defer m.storenodesByCommunityIDMutex.RUnlock()
msData, ok := m.storenodesByCommunityID[communityID]
return ok && len(msData.storenodes) > 0
}
// ReloadFromDB loads or reloads the mailservers from the database (on adding/deleting mailservers)
func (m *CommunityStorenodes) ReloadFromDB() error {
if m.storenodesDB == nil {
return nil
}
m.storenodesByCommunityIDMutex.Lock()
defer m.storenodesByCommunityIDMutex.Unlock()
dbNodes, err := m.storenodesDB.getAll()
if err != nil {
return err
}
// overwrite the in-memory storenodes
m.storenodesByCommunityID = make(map[string]storenodesData)
for _, node := range dbNodes {
communityID := node.CommunityID.String()
if _, ok := m.storenodesByCommunityID[communityID]; !ok {
m.storenodesByCommunityID[communityID] = storenodesData{}
}
data := m.storenodesByCommunityID[communityID]
data.storenodes = append(data.storenodes, node)
m.storenodesByCommunityID[communityID] = data
}
m.logger.Debug("loaded communities storenodes", zap.Int("count", len(dbNodes)))
return nil
}
func (m *CommunityStorenodes) UpdateStorenodesInDB(communityID types.HexBytes, snodes []Storenode, clock uint64) error {
if err := m.storenodesDB.syncSave(communityID, snodes, clock); err != nil {
return err
}
if err := m.ReloadFromDB(); err != nil {
return err
}
return nil
}
func (m *CommunityStorenodes) GetStorenodesFromDB(communityID types.HexBytes) ([]Storenode, error) {
return m.storenodesDB.getByCommunityID(communityID)
}