Merge pull request #226 from ssb-ngi-pointer/graceful-dashboard-timeout

fix potential deadlocks
This commit is contained in:
Henry 2021-05-31 10:45:31 +02:00 committed by GitHub
commit 0563e9bf3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 19 deletions

View File

@ -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
}

View File

@ -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)
}