Skip to content

Commit f01fe8b

Browse files
committed
Preserve order expected in match listings based on query term boosting.
1 parent 9fc139d commit f01fe8b

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr
99

1010
### Changed
1111
- Log more error information when InitModule hooks from Go runtime plugins return errors.
12+
- Preserve order expected in match listings based on query term boosting.
1213

1314
### Fixed
1415
- Improve leaderboard rank re-calculation when removing a leaderboard record.

server/match_registry.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
209209

210210
var modes map[uint8]*uint8
211211
var labelResults *bleve.SearchResult
212+
var orderRequired bool
212213
if query != nil {
213214
if authoritative != nil && !authoritative.Value {
214215
// A filter on query is requested but authoritative matches are not allowed.
@@ -241,6 +242,8 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
241242

242243
// Because we have a query filter only authoritative matches are eligible.
243244
modes = MatchFilterAuthoritative
245+
// The query may contain boosting, in which case the order of results matters.
246+
orderRequired = true
244247
} else if label != nil {
245248
if authoritative != nil && !authoritative.Value {
246249
// A filter on label is requested but authoritative matches are not allowed.
@@ -302,6 +305,63 @@ func (r *LocalMatchRegistry) ListMatches(ctx context.Context, limit int, authori
302305
return make([]*api.Match, 0), nil
303306
}
304307

308+
// There is a query which may contain boosted search terms, which means order of results matters.
309+
if orderRequired {
310+
// Look up tracker info to determine match sizes.
311+
// This info is needed even if there is no min/max size filter because it's returned in results.
312+
matches := r.tracker.CountByStreamModeFilter(modes)
313+
matchSizes := make(map[string]int32, len(matches))
314+
for stream, size := range matches {
315+
matchSizes[fmt.Sprintf("%v.%v", stream.Subject.String(), stream.Label)] = size
316+
}
317+
318+
// Results.
319+
results := make([]*api.Match, 0, limit)
320+
321+
for _, hit := range labelResults.Hits {
322+
id := fmt.Sprintf("%v.%v", hit.ID, r.node)
323+
324+
// Size may be 0.
325+
size := matchSizes[id]
326+
327+
if minSize != nil && minSize.Value > size {
328+
// Not eligible based on minimum size.
329+
continue
330+
}
331+
332+
if maxSize != nil && maxSize.Value < size {
333+
// Not eligible based on maximum size.
334+
continue
335+
}
336+
337+
var labelString string
338+
if l, ok := hit.Fields["label_string"]; ok {
339+
if labelString, ok = l.(string); !ok {
340+
r.logger.Warn("Field not a string in match registry label cache: label_string")
341+
continue
342+
}
343+
} else {
344+
r.logger.Warn("Field not found in match registry label cache: label_string")
345+
continue
346+
}
347+
348+
results = append(results, &api.Match{
349+
MatchId: id,
350+
Authoritative: true,
351+
Label: &wrappers.StringValue{Value: labelString},
352+
Size: size,
353+
})
354+
if len(results) == limit {
355+
return results, nil
356+
}
357+
}
358+
359+
// We're in the query case, non-authoritative matches are not eligible so return what we can.
360+
return results, nil
361+
}
362+
363+
// It was not a query so ordering does not matter, move on to process the minimal set possible in any order.
364+
305365
// Match labels will only be nil if there is no label filter, no query filter, and authoritative is strictly false.
306366
// Therefore authoritative matches will never be part of this listing at all.
307367
var matchLabels map[uuid.UUID]*wrappers.StringValue

0 commit comments

Comments
 (0)