Wakeups largely working

This commit is contained in:
Neil Alexander 2021-01-06 10:17:34 +00:00
parent 475ae4ca3b
commit b353c039ff
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
6 changed files with 80 additions and 63 deletions

View file

@ -46,13 +46,15 @@ func (p *PDUStreamProvider) StreamRange(
device *userapi.Device, device *userapi.Device,
from, to types.StreamingToken, from, to types.StreamingToken,
filter gomatrixserverlib.EventFilter, filter gomatrixserverlib.EventFilter,
) (newPos types.StreamPosition) { ) (newPos types.StreamingToken) {
r := types.Range{ r := types.Range{
From: from.PDUPosition, From: from.PDUPosition,
To: to.PDUPosition, To: to.PDUPosition,
Backwards: from.IsAfter(to), Backwards: from.IsAfter(to),
} }
newPos = from.PDUPosition newPos = types.StreamingToken{
PDUPosition: from.PDUPosition,
}
var err error var err error
var events []types.StreamEvent var events []types.StreamEvent
@ -96,8 +98,8 @@ func (p *PDUStreamProvider) StreamRange(
), ),
) )
if event.StreamPosition > newPos { if event.StreamPosition > newPos.PDUPosition {
newPos = event.StreamPosition newPos.PDUPosition = event.StreamPosition
} }
} }
@ -123,7 +125,7 @@ func (p *PDUStreamProvider) StreamNotifyAfter(
check := func() bool { check := func() bool {
p.latestMutex.RLock() p.latestMutex.RLock()
defer p.latestMutex.RUnlock() defer p.latestMutex.RUnlock()
if from.PDUPosition > p.latest { if p.latest > from.PDUPosition {
close(ch) close(ch)
return true return true
} }
@ -167,9 +169,11 @@ func (p *PDUStreamProvider) StreamNotifyAfter(
func (p *PDUStreamProvider) StreamLatestPosition( func (p *PDUStreamProvider) StreamLatestPosition(
ctx context.Context, ctx context.Context,
) types.StreamPosition { ) types.StreamingToken {
p.latestMutex.RLock() p.latestMutex.RLock()
defer p.latestMutex.RUnlock() defer p.latestMutex.RUnlock()
return p.latest return types.StreamingToken{
PDUPosition: p.latest,
}
} }

View file

@ -37,8 +37,8 @@ func (p *TypingStreamProvider) StreamRange(
device *userapi.Device, device *userapi.Device,
from, to types.StreamingToken, from, to types.StreamingToken,
filter gomatrixserverlib.EventFilter, filter gomatrixserverlib.EventFilter,
) types.StreamPosition { ) types.StreamingToken {
return 0 return types.StreamingToken{}
} }
func (p *TypingStreamProvider) StreamNotifyAfter( func (p *TypingStreamProvider) StreamNotifyAfter(
@ -50,7 +50,7 @@ func (p *TypingStreamProvider) StreamNotifyAfter(
check := func() bool { check := func() bool {
p.latestMutex.RLock() p.latestMutex.RLock()
defer p.latestMutex.RUnlock() defer p.latestMutex.RUnlock()
if from.TypingPosition > p.latest { if p.latest > from.TypingPosition {
close(ch) close(ch)
return true return true
} }
@ -94,9 +94,11 @@ func (p *TypingStreamProvider) StreamNotifyAfter(
func (p *TypingStreamProvider) StreamLatestPosition( func (p *TypingStreamProvider) StreamLatestPosition(
ctx context.Context, ctx context.Context,
) types.StreamPosition { ) types.StreamingToken {
p.latestMutex.RLock() p.latestMutex.RLock()
defer p.latestMutex.RUnlock() defer p.latestMutex.RUnlock()
return p.latest return types.StreamingToken{
TypingPosition: p.latest,
}
} }

View file

@ -354,7 +354,8 @@ func (d *Database) WriteEvent(
return fmt.Errorf("d.OutputEvents.InsertEvent: %w", err) return fmt.Errorf("d.OutputEvents.InsertEvent: %w", err)
} }
pduPosition = pos pduPosition = pos
d.PDUStreamProvider.StreamAdvance(pduPosition)
d.PDUStreamProvider.StreamAdvance(pos)
if err = d.Topology.InsertEventInTopology(ctx, txn, ev, pos); err != nil { if err = d.Topology.InsertEventInTopology(ctx, txn, ev, pos); err != nil {
return fmt.Errorf("d.Topology.InsertEventInTopology: %w", err) return fmt.Errorf("d.Topology.InsertEventInTopology: %w", err)

View file

@ -22,10 +22,10 @@ func (p *PDUTopologyProvider) TopologyRange(ctx context.Context, res *types.Resp
_ = events _ = events
} }
func (p *PDUTopologyProvider) TopologyLatestPosition(ctx context.Context, roomID string) types.StreamPosition { func (p *PDUTopologyProvider) TopologyLatestPosition(ctx context.Context, roomID string) types.TopologyToken {
token, err := p.DB.MaxTopologicalPosition(ctx, roomID) token, err := p.DB.MaxTopologicalPosition(ctx, roomID)
if err != nil { if err != nil {
return 0 return types.TopologyToken{}
} }
return token.PDUPosition return token
} }

View file

@ -44,12 +44,15 @@ type RequestPool struct {
db storage.Database db storage.Database
cfg *config.SyncAPI cfg *config.SyncAPI
userAPI userapi.UserInternalAPI userAPI userapi.UserInternalAPI
Notifier *Notifier
keyAPI keyapi.KeyInternalAPI keyAPI keyapi.KeyInternalAPI
rsAPI roomserverAPI.RoomserverInternalAPI rsAPI roomserverAPI.RoomserverInternalAPI
lastseen sync.Map lastseen sync.Map
pduStream types.StreamProvider pduStream types.StreamProvider
typingStream types.StreamProvider typingStream types.StreamProvider
receiptStream types.StreamProvider
sendToDeviceStream types.StreamProvider
inviteStream types.StreamProvider
deviceListStream types.StreamProvider
} }
// NewRequestPool makes a new RequestPool // NewRequestPool makes a new RequestPool
@ -62,12 +65,15 @@ func NewRequestPool(
db: db, db: db,
cfg: cfg, cfg: cfg,
userAPI: userAPI, userAPI: userAPI,
Notifier: n,
keyAPI: keyAPI, keyAPI: keyAPI,
rsAPI: rsAPI, rsAPI: rsAPI,
lastseen: sync.Map{}, lastseen: sync.Map{},
pduStream: db.PDUStream(), pduStream: db.PDUStream(),
typingStream: db.TypingStream(), typingStream: db.TypingStream(),
receiptStream: nil, // TODO
sendToDeviceStream: nil, // TODO
inviteStream: nil, // TODO
deviceListStream: nil, // TODO
} }
go rp.cleanLastSeen() go rp.cleanLastSeen()
return rp return rp
@ -168,10 +174,6 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *userapi.
syncData = types.NewResponse() syncData = types.NewResponse()
filter := gomatrixserverlib.DefaultEventFilter() filter := gomatrixserverlib.DefaultEventFilter()
syncData.NextBatch = types.StreamingToken{
PDUPosition: rp.pduStream.StreamLatestPosition(syncReq.ctx),
TypingPosition: rp.typingStream.StreamLatestPosition(syncReq.ctx),
}
waitingSyncRequests.Inc() waitingSyncRequests.Inc()
defer waitingSyncRequests.Dec() defer waitingSyncRequests.Dec()
@ -181,31 +183,35 @@ func (rp *RequestPool) OnIncomingSyncRequest(req *http.Request, device *userapi.
defer timer.Stop() defer timer.Stop()
select { select {
case <-syncReq.ctx.Done(): case <-syncReq.ctx.Done(): // Caller gave up
// Caller gave up return util.JSONResponse{Code: http.StatusOK, JSON: syncData}
logger.Println("Context expired")
return util.JSONResponse{
Code: http.StatusOK,
JSON: syncData,
}
case <-timer.C: case <-timer.C: // Timeout reached
// Timeout reached return util.JSONResponse{Code: http.StatusOK, JSON: syncData}
logger.Println("Timed out")
return util.JSONResponse{
Code: http.StatusOK,
JSON: syncData,
}
case <-rp.pduStream.StreamNotifyAfter(syncReq.ctx, syncReq.since): case <-rp.pduStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
logger.Println("PDU stream awake")
case <-rp.typingStream.StreamNotifyAfter(syncReq.ctx, syncReq.since): case <-rp.typingStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
logger.Println("Typing stream awake") // case <-rp.receiptStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
// case <-rp.sendToDeviceStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
// case <-rp.inviteStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
// case <-rp.deviceListStream.StreamNotifyAfter(syncReq.ctx, syncReq.since):
} }
} }
syncData.NextBatch.PDUPosition = rp.pduStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, syncData.NextBatch, filter) var latest types.StreamingToken
syncData.NextBatch.TypingPosition = rp.typingStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, syncData.NextBatch, filter) latest.ApplyUpdates(rp.pduStream.StreamLatestPosition(syncReq.ctx))
latest.ApplyUpdates(rp.typingStream.StreamLatestPosition(syncReq.ctx))
// latest.ApplyUpdates(rp.receiptStream.StreamLatestPosition(syncReq.ctx))
// latest.ApplyUpdates(rp.sendToDeviceStream.StreamLatestPosition(syncReq.ctx))
// latest.ApplyUpdates(rp.inviteStream.StreamLatestPosition(syncReq.ctx))
// latest.ApplyUpdates(rp.deviceListStream.StreamLatestPosition(syncReq.ctx))
syncData.NextBatch.ApplyUpdates(rp.pduStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
syncData.NextBatch.ApplyUpdates(rp.typingStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
// syncData.NextBatch.ApplyUpdates(rp.receiptStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
// syncData.NextBatch.ApplyUpdates(rp.sendToDeviceStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
// syncData.NextBatch.ApplyUpdates(rp.inviteStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
// syncData.NextBatch.ApplyUpdates(rp.inviteStream.StreamRange(syncReq.ctx, syncData, device, syncReq.since, latest, filter))
return util.JSONResponse{ return util.JSONResponse{
Code: http.StatusOK, Code: http.StatusOK,
@ -333,7 +339,7 @@ func (rp *RequestPool) appendDeviceLists(
return data, nil return data, nil
} }
// nolint:gocyclo /*
func (rp *RequestPool) appendAccountData( func (rp *RequestPool) appendAccountData(
data *types.Response, userID string, req syncRequest, currentPos types.StreamPosition, data *types.Response, userID string, req syncRequest, currentPos types.StreamPosition,
accountDataFilter *gomatrixserverlib.EventFilter, accountDataFilter *gomatrixserverlib.EventFilter,
@ -443,6 +449,7 @@ func (rp *RequestPool) appendAccountData(
return data, nil return data, nil
} }
*/
// shouldReturnImmediately returns whether the /sync request is an initial sync, // shouldReturnImmediately returns whether the /sync request is an initial sync,
// or timeout=0, or full_state=true, in any of the cases the request should // or timeout=0, or full_state=true, in any of the cases the request should

View file

@ -9,19 +9,22 @@ import (
type StreamProvider interface { type StreamProvider interface {
StreamSetup() StreamSetup()
// StreamAdvance will update the latest position of the stream based on
// an update and will wake callers waiting on StreamNotifyAfter.
StreamAdvance(latest StreamPosition) StreamAdvance(latest StreamPosition)
// Range will update the response to include all updates between // StreamRange will update the response to include all updates between
// the from and to sync positions. It will always return immediately, // the from and to sync positions. It will always return immediately,
// making no changes if the range contains no updates. // making no changes if the range contains no updates.
StreamRange(ctx context.Context, res *Response, device *userapi.Device, from, to StreamingToken, filter gomatrixserverlib.EventFilter) StreamPosition StreamRange(ctx context.Context, res *Response, device *userapi.Device, from, to StreamingToken, filter gomatrixserverlib.EventFilter) StreamingToken
// NotifyAfter returns a channel which will be closed once the // StreamNotifyAfter returns a channel which will be closed once the
// stream advances past the "from" position. // stream advances past the "from" position.
StreamNotifyAfter(ctx context.Context, from StreamingToken) chan struct{} StreamNotifyAfter(ctx context.Context, from StreamingToken) chan struct{}
// LatestPosition returns the latest stream position for this stream. // StreamLatestPosition returns the latest stream position for this stream.
StreamLatestPosition(ctx context.Context) StreamPosition StreamLatestPosition(ctx context.Context) StreamingToken
} }
type TopologyProvider interface { type TopologyProvider interface {
@ -33,5 +36,5 @@ type TopologyProvider interface {
// LatestPosition returns the latest stream position for this stream // LatestPosition returns the latest stream position for this stream
// for the given room. // for the given room.
TopologyLatestPosition(ctx context.Context, roomID string) StreamPosition TopologyLatestPosition(ctx context.Context, roomID string) TopologyToken
} }