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()
|
||||
// add ref to to the room map
|
||||
m.room[who.Ref()] = edp
|
||||
currentMembers := m.room.AsList()
|
||||
m.roomMu.Unlock()
|
||||
// update all the connected tunnel.endpoints calls
|
||||
m.endpointsUpdater.Update(m.room.AsList())
|
||||
m.endpointsUpdater.Update(currentMembers)
|
||||
// update all the connected room.attendants calls
|
||||
m.attendantsUpdater.Joined(who)
|
||||
m.roomMu.Unlock()
|
||||
}
|
||||
|
||||
// Remove removes the peer from the room
|
||||
|
@ -97,11 +98,12 @@ func (m *Manager) Remove(who refs.FeedRef) {
|
|||
m.roomMu.Lock()
|
||||
// remove ref from lobby
|
||||
delete(m.room, who.Ref())
|
||||
currentMembers := m.room.AsList()
|
||||
m.roomMu.Unlock()
|
||||
// update all the connected tunnel.endpoints calls
|
||||
m.endpointsUpdater.Update(m.room.AsList())
|
||||
m.endpointsUpdater.Update(currentMembers)
|
||||
// update all the connected room.attendants calls
|
||||
m.attendantsUpdater.Left(who)
|
||||
m.roomMu.Unlock()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
m.roomMu.Lock()
|
||||
|
||||
var currentMembers []string
|
||||
// if the peer didn't call tunnel.announce()
|
||||
_, has := m.room[who.Ref()]
|
||||
if !has {
|
||||
// register them as if they didnt
|
||||
m.room[who.Ref()] = edp
|
||||
currentMembers = m.room.AsList()
|
||||
}
|
||||
m.roomMu.Unlock()
|
||||
|
||||
if !has {
|
||||
// update everyone
|
||||
m.endpointsUpdater.Update(m.room.AsList())
|
||||
m.endpointsUpdater.Update(currentMembers)
|
||||
m.attendantsUpdater.Joined(who)
|
||||
}
|
||||
|
||||
m.roomMu.Unlock()
|
||||
return has
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,11 @@ package admin
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.mindeco.de/http/render"
|
||||
"go.mindeco.de/log/level"
|
||||
"go.mindeco.de/logging"
|
||||
refs "go.mindeco.de/ssb-refs"
|
||||
|
||||
"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) {
|
||||
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))
|
||||
for i := range onlineRefs {
|
||||
ref, err := refs.ParseFeedRef(onlineRefs[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse online ref: %w", err)
|
||||
}
|
||||
onlineMembers[i], err = h.dbs.Members.GetByFeed(req.Context(), *ref)
|
||||
for i, ref := range onlineRefs {
|
||||
var err error
|
||||
onlineMembers[i], err = h.dbs.Members.GetByFeed(ctx, ref)
|
||||
if err != nil {
|
||||
// TODO: do we want to show "external users" (non-members) on the dashboard?
|
||||
return nil, fmt.Errorf("failed to lookup online member: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
onlineCount := len(onlineMembers)
|
||||
|
||||
memberCount, err := h.dbs.Members.Count(req.Context())
|
||||
memberCount, err := h.dbs.Members.Count(ctx)
|
||||
if err != nil {
|
||||
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 {
|
||||
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 {
|
||||
return nil, fmt.Errorf("failed to count denied keys: %w", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue