Add graph walking structs

This commit is contained in:
Kegan Dougal 2020-11-03 16:01:13 +00:00
parent 4dc9f3efd4
commit b8a89731dd

View file

@ -31,6 +31,8 @@ import (
"github.com/matrix-org/util" "github.com/matrix-org/util"
) )
const constRelType = "m.reference"
type EventRelationshipRequest struct { type EventRelationshipRequest struct {
EventID string `json:"event_id"` EventID string `json:"event_id"`
MaxDepth int `json:"max_depth"` MaxDepth int `json:"max_depth"`
@ -186,7 +188,7 @@ func includeParent(ctx context.Context, rsAPI roomserver.RoomserverInternalAPI,
// Apply history visibility checks to all these events and add the ones which pass into the response array, // Apply history visibility checks to all these events and add the ones which pass into the response array,
// honouring the recent_first flag and the limit. // honouring the recent_first flag and the limit.
func includeChildren(ctx context.Context, rsAPI roomserver.RoomserverInternalAPI, db Database, parentID string, limit int, recentFirst bool, userID string) ([]*gomatrixserverlib.HeaderedEvent, *util.JSONResponse) { func includeChildren(ctx context.Context, rsAPI roomserver.RoomserverInternalAPI, db Database, parentID string, limit int, recentFirst bool, userID string) ([]*gomatrixserverlib.HeaderedEvent, *util.JSONResponse) {
children, err := db.ChildrenForParent(ctx, parentID, "m.reference", recentFirst) children, err := db.ChildrenForParent(ctx, parentID, constRelType, recentFirst)
if err != nil { if err != nil {
util.GetLogger(ctx).WithError(err).Error("failed to get ChildrenForParent") util.GetLogger(ctx).WithError(err).Error("failed to get ChildrenForParent")
resErr := jsonerror.InternalServerError() resErr := jsonerror.InternalServerError()
@ -216,25 +218,29 @@ func walkThread(
return nil, false return nil, false
} }
var result []*gomatrixserverlib.HeaderedEvent var result []*gomatrixserverlib.HeaderedEvent
eventsToWalk := newWalker(req) eventWalker := walker{
parent, siblingNum, current := eventsToWalk.Next() ctx: ctx,
for current != "" { req: req,
db: db,
}
parent, current := eventWalker.Next()
for current.EventID != "" {
// If the response array is >= limit, stop. // If the response array is >= limit, stop.
if len(result) >= limit { if len(result) >= limit {
return result, true return result, true
} }
// If already processed event, skip. // If already processed event, skip.
if included[current] > 0 { if included[current.EventID] > 0 {
continue continue
} }
// Check how deep the event is compared to event_id, does it exceed (greater than) max_depth? If yes, skip. // Check how deep the event is compared to event_id, does it exceed (greater than) max_depth? If yes, skip.
parentDepth := included[parent] parentDepth := included[parent]
if parentDepth == 0 { if parentDepth == 0 {
util.GetLogger(ctx).Errorf("parent has unknown depth; this should be impossible, parent=%s curr=%s map=%v", parent, current, included) util.GetLogger(ctx).Errorf("parent has unknown depth; this should be impossible, parent=%s curr=%v map=%v", parent, current, included)
// set these at the max to stop walking this part of the DAG // set these at the max to stop walking this part of the DAG
included[parent] = req.MaxDepth included[parent] = req.MaxDepth
included[current] = req.MaxDepth included[current.EventID] = req.MaxDepth
continue continue
} }
depth := parentDepth + 1 depth := parentDepth + 1
@ -243,16 +249,16 @@ func walkThread(
} }
// Check what number child this event is (ordered by recent_first) compared to its parent, does it exceed (greater than) max_breadth? If yes, skip. // Check what number child this event is (ordered by recent_first) compared to its parent, does it exceed (greater than) max_breadth? If yes, skip.
if siblingNum > req.MaxBreadth { if current.SiblingNumber > req.MaxBreadth {
continue continue
} }
// Process the event. // Process the event.
event := getEventIfVisible(ctx, rsAPI, current, userID) event := getEventIfVisible(ctx, rsAPI, current.EventID, userID)
if event != nil { if event != nil {
result = append(result, event) result = append(result, event)
} }
included[current] = depth included[current.EventID] = depth
} }
return result, false return result, false
} }
@ -291,40 +297,28 @@ func getEventIfVisible(ctx context.Context, rsAPI roomserver.RoomserverInternalA
return &event return &event
} }
// walker walks the thread DAG type walkInfo struct {
type walker interface { eventInfo
// Next returns the next event. `current` is the event ID being walked. SiblingNumber int
// `parent` is the parent of `current`. `siblingNum` is the sibling number of `current`, starting
// from one.
Next() (parent string, siblingNum int, current string)
} }
func newWalker(req *EventRelationshipRequest) walker { type walker struct {
if *req.DepthFirst { ctx context.Context
return &depthWalker{ req *EventRelationshipRequest
req: req, db Database
current: req.EventID,
}
}
return &breadthWalker{req}
}
type depthWalker struct {
req *EventRelationshipRequest
// db Database
current string current string
//toProcess []walkInfo
} }
func (w *depthWalker) Next() (parent string, siblingNum int, current string) { // Next returns the next event to process.
func (w *walker) Next() (parent string, current walkInfo) {
//var events []string //var events []string
//children, err := w.db.ChildrenForParent(w.ctx, w.current)
return "", 0, ""
}
type breadthWalker struct { _, err := w.db.ChildrenForParent(w.ctx, w.current, constRelType, *w.req.RecentFirst)
req *EventRelationshipRequest if err != nil {
} util.GetLogger(w.ctx).WithError(err).Error("Next() failed, cannot walk")
return
}
func (w *breadthWalker) Next() (parent string, siblingNum int, current string) { return
return "", 0, ""
} }