diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2024-07-10 14:39:34 +0200 |
|---|---|---|
| committer | Jeroen Wijenbergh <46386452+jwijenbergh@users.noreply.github.com> | 2024-07-17 14:00:03 +0000 |
| commit | a1879195a727d7b90347ed11f86d85fac6541df7 (patch) | |
| tree | ef19423671009552181f759b4a9162e7d91bf82a /client/discovery.go | |
| parent | 7f8af5845ddec1816f93a2cb013f0818c19caab3 (diff) | |
Client + Discovery: Fetch dscovery at startup using DiscoveryStartup
With a manager that locks and copies such that no race conditions happen
Diffstat (limited to 'client/discovery.go')
| -rw-r--r-- | client/discovery.go | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/client/discovery.go b/client/discovery.go index 415be9b..2758678 100644 --- a/client/discovery.go +++ b/client/discovery.go @@ -1,9 +1,13 @@ package client import ( + "context" "sort" "strings" + "sync" + "github.com/eduvpn/eduvpn-common/internal/discovery" + "github.com/eduvpn/eduvpn-common/internal/log" "github.com/eduvpn/eduvpn-common/i18nerr" "github.com/eduvpn/eduvpn-common/types/cookie" discotypes "github.com/eduvpn/eduvpn-common/types/discovery" @@ -24,7 +28,10 @@ func (c *Client) DiscoOrganizations(ck *cookie.Cookie, search string) (*discotyp return nil, i18nerr.NewInternal("Server/organization discovery with this client ID is not supported") } - orgs, fresh, err := c.cfg.Discovery().Organizations(ck.Context()) + disco, release := c.discoMan.Discovery(true) + defer release() + + orgs, fresh, err := disco.Organizations(ck.Context()) if fresh { defer c.TrySave() } @@ -70,7 +77,9 @@ func (c *Client) DiscoServers(ck *cookie.Cookie, search string) (*discotypes.Ser return nil, i18nerr.NewInternal("Server/organization discovery with this client ID is not supported") } - servs, fresh, err := c.cfg.Discovery().Servers(ck.Context()) + disco, release := c.discoMan.Discovery(true) + defer release() + servs, fresh, err := disco.Servers(ck.Context()) if fresh { defer c.TrySave() } @@ -105,3 +114,70 @@ func (c *Client) DiscoServers(ck *cookie.Cookie, search string) (*discotypes.Ser List: retServs, }, err } + +type DiscoManager struct { + disco *discovery.Discovery + + cancel context.CancelFunc + mu sync.RWMutex + wait sync.WaitGroup +} + +func (m *DiscoManager) lock(write bool) { + if write { + m.mu.Lock() + return + } + m.mu.RLock() +} + +func (m *DiscoManager) unlock(write bool) { + if write { + m.mu.Unlock() + return + } + m.mu.RUnlock() +} + +func (m *DiscoManager) Discovery(write bool) (*discovery.Discovery, func()) { + if write { + m.wait.Wait() + } + m.lock(write) + return m.disco, func() { + m.unlock(write) + } +} + +func (m *DiscoManager) Cancel() { + if m.cancel != nil { + m.cancel() + } + m.wait.Wait() +} + +func (m *DiscoManager) Startup(ctx context.Context, cb func()) { + ctx, cancel := context.WithCancel(ctx) + m.cancel = cancel + m.wait.Add(1) + go func() { + defer m.wait.Done() + m.lock(false) + discoCopy, err := m.disco.Copy() + if err != nil { + log.Logger.Warningf("internal error, failed to clone discovery, %v", err) + return + } + m.unlock(false) + // we already log the warning + discoCopy.Servers(ctx) //nolint:errcheck + + m.lock(true) + m.disco.UpdateServers(discoCopy) + m.unlock(true) + + if cb != nil { + cb() + } + }() +} |
