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