smegmesh/pkg/sync/syncer.go

98 lines
1.8 KiB
Go
Raw Normal View History

2023-10-10 21:14:40 +02:00
package sync
import (
"errors"
2023-10-23 19:13:08 +02:00
"sync"
"time"
crdt "github.com/tim-beatham/wgmesh/pkg/automerge"
"github.com/tim-beatham/wgmesh/pkg/lib"
logging "github.com/tim-beatham/wgmesh/pkg/log"
"github.com/tim-beatham/wgmesh/pkg/mesh"
)
2023-10-10 21:14:40 +02:00
// Syncer: picks random nodes from the mesh
type Syncer interface {
Sync(meshId string) error
SyncMeshes() error
}
type SyncerImpl struct {
manager *mesh.MeshManager
requester SyncRequester
authenticatedNodes []crdt.MeshNodeCrdt
2023-10-10 21:14:40 +02:00
}
const subSetLength = 3
2023-10-10 21:14:40 +02:00
// Sync: Sync random nodes
func (s *SyncerImpl) Sync(meshId string) error {
if !s.manager.HasChanges(meshId) {
logging.Log.WriteInfof("No changes for %s", meshId)
return nil
}
mesh := s.manager.GetMesh(meshId)
if mesh == nil {
return errors.New("the provided mesh does not exist")
}
snapshot, err := mesh.GetMesh()
if err != nil {
return err
}
nodes := snapshot.GetNodes()
if len(nodes) <= 1 {
return nil
}
excludedNodes := map[string]struct{}{
s.manager.HostParameters.HostEndpoint: {},
}
meshNodes := lib.MapValuesWithExclude(nodes, excludedNodes)
randomSubset := lib.RandomSubsetOfLength(meshNodes, subSetLength)
before := time.Now()
2023-10-23 19:13:08 +02:00
var waitGroup sync.WaitGroup
for _, n := range randomSubset {
2023-10-23 19:13:08 +02:00
waitGroup.Add(1)
2023-10-23 19:13:08 +02:00
syncMeshFunc := func() error {
defer waitGroup.Done()
err := s.requester.SyncMesh(meshId, n.GetHostEndpoint())
return err
}
2023-10-23 19:13:08 +02:00
go syncMeshFunc()
}
2023-10-23 19:13:08 +02:00
waitGroup.Wait()
logging.Log.WriteInfof("SYNC TIME: %v", time.Now().Sub(before))
2023-10-10 21:14:40 +02:00
return nil
}
// SyncMeshes: Sync all meshes
2023-10-10 21:14:40 +02:00
func (s *SyncerImpl) SyncMeshes() error {
for meshId, _ := range s.manager.Meshes {
err := s.Sync(meshId)
if err != nil {
return err
}
}
return nil
2023-10-10 21:14:40 +02:00
}
func NewSyncer(m *mesh.MeshManager, r SyncRequester) Syncer {
return &SyncerImpl{manager: m, requester: r}
}