Merge pull request #226 from ssb-ngi-pointer/graceful-dashboard-timeout
fix potential deadlocks
This commit is contained in:
commit
0563e9bf3a
|
@ -85,11 +85,12 @@ func (m *Manager) AddEndpoint(who refs.FeedRef, edp muxrpc.Endpoint) {
|
||||||
m.roomMu.Lock()
|
m.roomMu.Lock()
|
||||||
// add ref to to the room map
|
// add ref to to the room map
|
||||||
m.room[who.Ref()] = edp
|
m.room[who.Ref()] = edp
|
||||||
|
currentMembers := m.room.AsList()
|
||||||
|
m.roomMu.Unlock()
|
||||||
// update all the connected tunnel.endpoints calls
|
// update all the connected tunnel.endpoints calls
|
||||||
m.endpointsUpdater.Update(m.room.AsList())
|
m.endpointsUpdater.Update(currentMembers)
|
||||||
// update all the connected room.attendants calls
|
// update all the connected room.attendants calls
|
||||||
m.attendantsUpdater.Joined(who)
|
m.attendantsUpdater.Joined(who)
|
||||||
m.roomMu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the peer from the room
|
// Remove removes the peer from the room
|
||||||
|
@ -97,11 +98,12 @@ func (m *Manager) Remove(who refs.FeedRef) {
|
||||||
m.roomMu.Lock()
|
m.roomMu.Lock()
|
||||||
// remove ref from lobby
|
// remove ref from lobby
|
||||||
delete(m.room, who.Ref())
|
delete(m.room, who.Ref())
|
||||||
|
currentMembers := m.room.AsList()
|
||||||
|
m.roomMu.Unlock()
|
||||||
// update all the connected tunnel.endpoints calls
|
// update all the connected tunnel.endpoints calls
|
||||||
m.endpointsUpdater.Update(m.room.AsList())
|
m.endpointsUpdater.Update(currentMembers)
|
||||||
// update all the connected room.attendants calls
|
// update all the connected room.attendants calls
|
||||||
m.attendantsUpdater.Left(who)
|
m.attendantsUpdater.Left(who)
|
||||||
m.roomMu.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlreadyAdded returns true if the peer was already added to the room.
|
// AlreadyAdded returns true if the peer was already added to the room.
|
||||||
|
@ -109,18 +111,22 @@ func (m *Manager) Remove(who refs.FeedRef) {
|
||||||
func (m *Manager) AlreadyAdded(who refs.FeedRef, edp muxrpc.Endpoint) bool {
|
func (m *Manager) AlreadyAdded(who refs.FeedRef, edp muxrpc.Endpoint) bool {
|
||||||
m.roomMu.Lock()
|
m.roomMu.Lock()
|
||||||
|
|
||||||
|
var currentMembers []string
|
||||||
// if the peer didn't call tunnel.announce()
|
// if the peer didn't call tunnel.announce()
|
||||||
_, has := m.room[who.Ref()]
|
_, has := m.room[who.Ref()]
|
||||||
if !has {
|
if !has {
|
||||||
// register them as if they didnt
|
// register them as if they didnt
|
||||||
m.room[who.Ref()] = edp
|
m.room[who.Ref()] = edp
|
||||||
|
currentMembers = m.room.AsList()
|
||||||
|
}
|
||||||
|
m.roomMu.Unlock()
|
||||||
|
|
||||||
|
if !has {
|
||||||
// update everyone
|
// update everyone
|
||||||
m.endpointsUpdater.Update(m.room.AsList())
|
m.endpointsUpdater.Update(currentMembers)
|
||||||
m.attendantsUpdater.Joined(who)
|
m.attendantsUpdater.Joined(who)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.roomMu.Unlock()
|
|
||||||
return has
|
return has
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,11 @@ package admin
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"go.mindeco.de/http/render"
|
"go.mindeco.de/http/render"
|
||||||
|
"go.mindeco.de/log/level"
|
||||||
|
"go.mindeco.de/logging"
|
||||||
refs "go.mindeco.de/ssb-refs"
|
refs "go.mindeco.de/ssb-refs"
|
||||||
|
|
||||||
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
"github.com/ssb-ngi-pointer/go-ssb-room/internal/network"
|
||||||
|
@ -25,36 +28,53 @@ type dashboardHandler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h dashboardHandler) overview(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
func (h dashboardHandler) overview(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
roomRef := h.netInfo.RoomID.Ref()
|
var (
|
||||||
|
ctx = req.Context()
|
||||||
|
roomRef = h.netInfo.RoomID.Ref()
|
||||||
|
|
||||||
onlineRefs := h.roomState.List()
|
onlineRefs []refs.FeedRef
|
||||||
|
refsUpdateCh = make(chan []refs.FeedRef)
|
||||||
|
onlineCount = -1
|
||||||
|
)
|
||||||
|
|
||||||
|
// this is an attempt to sidestep the _dashboard doesn't render_ bug (issue #210)
|
||||||
|
// first we retreive the member state via a goroutine in the background
|
||||||
|
go func() {
|
||||||
|
refsUpdateCh <- h.roomState.ListAsRefs()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// if it doesn't complete in 10 seconds the slice stays empty and onlineCount remains -1 (to indicate a problem)
|
||||||
|
select {
|
||||||
|
case <-time.After(10 * time.Second):
|
||||||
|
logger := logging.FromContext(ctx)
|
||||||
|
level.Warn(logger).Log("event", "didnt retreive room state in time")
|
||||||
|
|
||||||
|
case onlineRefs = <-refsUpdateCh:
|
||||||
|
onlineCount = len(onlineRefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// in the timeout case, nothing will happen here since the onlineRefs slice is empty
|
||||||
onlineMembers := make([]roomdb.Member, len(onlineRefs))
|
onlineMembers := make([]roomdb.Member, len(onlineRefs))
|
||||||
for i := range onlineRefs {
|
for i, ref := range onlineRefs {
|
||||||
ref, err := refs.ParseFeedRef(onlineRefs[i])
|
var err error
|
||||||
if err != nil {
|
onlineMembers[i], err = h.dbs.Members.GetByFeed(ctx, ref)
|
||||||
return nil, fmt.Errorf("failed to parse online ref: %w", err)
|
|
||||||
}
|
|
||||||
onlineMembers[i], err = h.dbs.Members.GetByFeed(req.Context(), *ref)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: do we want to show "external users" (non-members) on the dashboard?
|
// TODO: do we want to show "external users" (non-members) on the dashboard?
|
||||||
return nil, fmt.Errorf("failed to lookup online member: %w", err)
|
return nil, fmt.Errorf("failed to lookup online member: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onlineCount := len(onlineMembers)
|
memberCount, err := h.dbs.Members.Count(ctx)
|
||||||
|
|
||||||
memberCount, err := h.dbs.Members.Count(req.Context())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count members: %w", err)
|
return nil, fmt.Errorf("failed to count members: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
inviteCount, err := h.dbs.Invites.Count(req.Context())
|
inviteCount, err := h.dbs.Invites.Count(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count invites: %w", err)
|
return nil, fmt.Errorf("failed to count invites: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
deniedCount, err := h.dbs.DeniedKeys.Count(req.Context())
|
deniedCount, err := h.dbs.DeniedKeys.Count(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to count denied keys: %w", err)
|
return nil, fmt.Errorf("failed to count denied keys: %w", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue