configuration to space
This commit is contained in:
parent
fe2c8bdade
commit
f41a7f8c6a
@ -2,6 +2,7 @@ package configuration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/peer"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
|
||||||
"github.com/anytypeio/go-chash"
|
"github.com/anytypeio/go-chash"
|
||||||
@ -12,15 +13,23 @@ func New() Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Configuration interface {
|
type Configuration interface {
|
||||||
|
// Id returns current configuration id
|
||||||
Id() string
|
Id() string
|
||||||
|
// AllPeers returns all peers by spaceId except current account
|
||||||
AllPeers(ctx context.Context, spaceId string) (peers []peer.Peer, err error)
|
AllPeers(ctx context.Context, spaceId string) (peers []peer.Peer, err error)
|
||||||
|
// OnePeer returns one of peer for spaceId
|
||||||
OnePeer(ctx context.Context, spaceId string) (p peer.Peer, err error)
|
OnePeer(ctx context.Context, spaceId string) (p peer.Peer, err error)
|
||||||
|
// NodeIds returns list of peerId for given spaceId
|
||||||
|
NodeIds(spaceId string) []string
|
||||||
|
// IsResponsible checks if current account responsible for given spaceId
|
||||||
|
IsResponsible(spaceId string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
id string
|
id string
|
||||||
pool pool.Pool
|
accountId string
|
||||||
chash chash.CHash
|
pool pool.Pool
|
||||||
|
chash chash.CHash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *configuration) Id() string {
|
func (c *configuration) Id() string {
|
||||||
@ -28,11 +37,41 @@ func (c *configuration) Id() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *configuration) AllPeers(ctx context.Context, spaceId string) (peers []peer.Peer, err error) {
|
func (c *configuration) AllPeers(ctx context.Context, spaceId string) (peers []peer.Peer, err error) {
|
||||||
//TODO implement me
|
nodeIds := c.NodeIds(spaceId)
|
||||||
panic("implement me")
|
peers = make([]peer.Peer, 0, len(nodeIds))
|
||||||
|
for _, id := range nodeIds {
|
||||||
|
p, e := c.pool.DialAndAddPeer(ctx, id)
|
||||||
|
if e == nil {
|
||||||
|
peers = append(peers, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(peers) == 0 {
|
||||||
|
return nil, fmt.Errorf("unable to connect to any node")
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *configuration) OnePeer(ctx context.Context, spaceId string) (p peer.Peer, err error) {
|
func (c *configuration) OnePeer(ctx context.Context, spaceId string) (p peer.Peer, err error) {
|
||||||
//TODO implement me
|
nodeIds := c.NodeIds(spaceId)
|
||||||
panic("implement me")
|
return c.pool.GetOrDialOneOf(ctx, nodeIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configuration) NodeIds(spaceId string) []string {
|
||||||
|
members := c.chash.GetMembers(spaceId)
|
||||||
|
res := make([]string, 0, len(members))
|
||||||
|
for _, m := range members {
|
||||||
|
if m.Id() != c.accountId {
|
||||||
|
res = append(res, m.Id())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configuration) IsResponsible(spaceId string) bool {
|
||||||
|
for _, m := range c.chash.GetMembers(spaceId) {
|
||||||
|
if m.Id() == c.accountId {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,8 +38,9 @@ func (s *service) Init(ctx context.Context, a *app.App) (err error) {
|
|||||||
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
||||||
configNodes := a.MustComponent(node.CName).(node.Service).Nodes()
|
configNodes := a.MustComponent(node.CName).(node.Service).Nodes()
|
||||||
config := &configuration{
|
config := &configuration{
|
||||||
id: "config",
|
id: "config",
|
||||||
pool: s.pool,
|
accountId: s.accountId,
|
||||||
|
pool: s.pool,
|
||||||
}
|
}
|
||||||
if config.chash, err = chash.New(chash.Config{
|
if config.chash, err = chash.New(chash.Config{
|
||||||
PartitionCount: partitionCount,
|
PartitionCount: partitionCount,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
@ -34,11 +35,12 @@ func NewPool() Pool {
|
|||||||
type Handler func(ctx context.Context, msg *Message) (err error)
|
type Handler func(ctx context.Context, msg *Message) (err error)
|
||||||
|
|
||||||
type Pool interface {
|
type Pool interface {
|
||||||
DialAndAddPeer(ctx context.Context, id string) (err error)
|
|
||||||
AddAndReadPeer(peer peer.Peer) (err error)
|
AddAndReadPeer(peer peer.Peer) (err error)
|
||||||
AddHandler(msgType syncproto.MessageType, h Handler)
|
AddHandler(msgType syncproto.MessageType, h Handler)
|
||||||
AddPeerIdToGroup(peerId, groupId string) (err error)
|
AddPeerIdToGroup(peerId, groupId string) (err error)
|
||||||
RemovePeerIdFromGroup(peerId, groupId string) (err error)
|
RemovePeerIdFromGroup(peerId, groupId string) (err error)
|
||||||
|
DialAndAddPeer(ctx context.Context, id string) (peer.Peer, error)
|
||||||
|
GetOrDialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error)
|
||||||
|
|
||||||
SendAndWait(ctx context.Context, peerId string, msg *syncproto.Message) (err error)
|
SendAndWait(ctx context.Context, peerId string, msg *syncproto.Message) (err error)
|
||||||
SendAndWaitResponse(ctx context.Context, id string, s *syncproto.Message) (resp *Message, err error)
|
SendAndWaitResponse(ctx context.Context, id string, s *syncproto.Message) (resp *Message, err error)
|
||||||
@ -89,25 +91,29 @@ func (p *pool) AddHandler(msgType syncproto.MessageType, h Handler) {
|
|||||||
p.handlers[msgType] = append(p.handlers[msgType], h)
|
p.handlers[msgType] = append(p.handlers[msgType], h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pool) DialAndAddPeer(ctx context.Context, peerId string) (err error) {
|
func (p *pool) DialAndAddPeer(ctx context.Context, peerId string) (peer.Peer, error) {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
if p.closed {
|
if p.closed {
|
||||||
return ErrPoolClosed
|
return nil, ErrPoolClosed
|
||||||
}
|
}
|
||||||
if _, ok := p.peersById[peerId]; ok {
|
return p.dialAndAdd(ctx, peerId)
|
||||||
return nil
|
}
|
||||||
|
|
||||||
|
func (p *pool) dialAndAdd(ctx context.Context, peerId string) (peer.Peer, error) {
|
||||||
|
if peer, ok := p.peersById[peerId]; ok {
|
||||||
|
return peer.peer, nil
|
||||||
}
|
}
|
||||||
peer, err := p.dialer.Dial(ctx, peerId)
|
peer, err := p.dialer.Dial(ctx, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
p.peersById[peer.Id()] = &peerEntry{
|
p.peersById[peer.Id()] = &peerEntry{
|
||||||
peer: peer,
|
peer: peer,
|
||||||
}
|
}
|
||||||
p.wg.Add(1)
|
p.wg.Add(1)
|
||||||
go p.readPeerLoop(peer)
|
go p.readPeerLoop(peer)
|
||||||
return nil
|
return peer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pool) AddAndReadPeer(peer peer.Peer) (err error) {
|
func (p *pool) AddAndReadPeer(peer peer.Peer) (err error) {
|
||||||
@ -211,6 +217,38 @@ func (p *pool) SendAndWaitResponse(ctx context.Context, peerId string, msg *sync
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *pool) GetOrDialOneOf(ctx context.Context, peerIds []string) (peer.Peer, error) {
|
||||||
|
p.mu.RLock()
|
||||||
|
if p.closed {
|
||||||
|
p.mu.RUnlock()
|
||||||
|
return nil, ErrPoolClosed
|
||||||
|
}
|
||||||
|
for _, peerId := range peerIds {
|
||||||
|
peer, ok := p.peersById[peerId]
|
||||||
|
if ok {
|
||||||
|
p.mu.RUnlock()
|
||||||
|
return peer.peer, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.mu.RUnlock()
|
||||||
|
rand.Shuffle(len(peerIds), func(i, j int) {
|
||||||
|
peerIds[i], peerIds[j] = peerIds[j], peerIds[i]
|
||||||
|
})
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
var lastErr error
|
||||||
|
for _, peerId := range peerIds {
|
||||||
|
peer, err := p.dialAndAdd(ctx, peerId)
|
||||||
|
if err != nil {
|
||||||
|
lastErr = err
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return peer, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, lastErr
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pool) Broadcast(ctx context.Context, groupId string, msg *syncproto.Message) (err error) {
|
func (p *pool) Broadcast(ctx context.Context, groupId string, msg *syncproto.Message) (err error) {
|
||||||
//TODO implement me
|
//TODO implement me
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/config"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/configuration"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool/handler"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/net/pool/handler"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/spacesync"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/spacesync"
|
||||||
@ -29,17 +30,20 @@ type Service interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
conf config.Space
|
conf config.Space
|
||||||
cache ocache.OCache
|
cache ocache.OCache
|
||||||
pool pool.Pool
|
pool pool.Pool
|
||||||
|
confService configuration.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
|
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
|
||||||
s.conf = a.MustComponent(config.CName).(*config.Config).Space
|
s.conf = a.MustComponent(config.CName).(*config.Config).Space
|
||||||
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
s.pool = a.MustComponent(pool.CName).(pool.Pool)
|
||||||
|
s.confService = a.MustComponent(configuration.CName).(configuration.Service)
|
||||||
ttlSec := time.Second * time.Duration(s.conf.GCTTL)
|
ttlSec := time.Second * time.Duration(s.conf.GCTTL)
|
||||||
s.cache = ocache.New(s.loadSpace, ocache.WithTTL(ttlSec), ocache.WithGCPeriod(time.Minute))
|
s.cache = ocache.New(s.loadSpace, ocache.WithTTL(ttlSec), ocache.WithGCPeriod(time.Minute))
|
||||||
s.pool.AddHandler(syncproto.MessageType_MessageTypeSpace, handler.Reply{ReplyHandler: s}.Handle)
|
s.pool.AddHandler(syncproto.MessageType_MessageTypeSpace, handler.Reply{ReplyHandler: s}.Handle)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +57,7 @@ func (s *service) Run(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
|
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
|
||||||
// TODO: load from database here
|
// TODO: load from database here
|
||||||
sp := &space{s: s, id: id}
|
sp := &space{s: s, id: id, conf: s.confService.GetLast()}
|
||||||
if err = sp.Run(ctx); err != nil {
|
if err = sp.Run(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ldiff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ldiff"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/configuration"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/remotediff"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/remotediff"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/spacesync"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/space/spacesync"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -21,8 +22,8 @@ type Space interface {
|
|||||||
//
|
//
|
||||||
|
|
||||||
type space struct {
|
type space struct {
|
||||||
id string
|
id string
|
||||||
|
conf configuration.Configuration
|
||||||
diff ldiff.Diff
|
diff ldiff.Diff
|
||||||
diffHandler func()
|
diffHandler func()
|
||||||
syncCtx context.Context
|
syncCtx context.Context
|
||||||
@ -105,10 +106,47 @@ func (s *space) syncLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *space) sync(ctx context.Context) error {
|
func (s *space) sync(ctx context.Context) error {
|
||||||
|
peerIds, err := s.peerIds(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, peerId := range peerIds {
|
||||||
|
if err := s.syncWithPeer(ctx, peerId); err != nil {
|
||||||
|
log.Error("can't sync with peer", zap.String("peer", peerId), zap.Error(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *space) syncWithPeer(ctx context.Context, peerId string) (err error) {
|
||||||
|
rdiff := remotediff.NewRemoteDiff(s.s.pool, peerId, s.id)
|
||||||
|
newIds, changedIds, removedIds, err := s.diff.Diff(ctx, rdiff)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Info("sync done:", zap.Strings("newIds", newIds), zap.Strings("changedIds", changedIds), zap.Strings("removedIds", removedIds))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *space) peerIds(ctx context.Context) (peerIds []string, err error) {
|
||||||
|
if s.conf.IsResponsible(s.id) {
|
||||||
|
peers, err := s.conf.AllPeers(ctx, s.id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, p := range peers {
|
||||||
|
peerIds = append(peerIds, p.Id())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peer, err := s.conf.OnePeer(ctx, s.id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
peerIds = append(peerIds, peer.Id())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (s *space) Close() error {
|
func (s *space) Close() error {
|
||||||
s.syncCancel()
|
s.syncCancel()
|
||||||
<-s.syncLoopDone
|
<-s.syncLoopDone
|
||||||
|
|||||||
@ -75,7 +75,7 @@ func (s *service) HandleMessage(ctx context.Context, msg *pool.Message) (err err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) SendMessageAsync(peerId string, msg *syncproto.Sync) (err error) {
|
func (s *service) SendMessageAsync(peerId string, msg *syncproto.Sync) (err error) {
|
||||||
err = s.pool.DialAndAddPeer(context.Background(), peerId)
|
_, err = s.pool.DialAndAddPeer(context.Background(), peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user