check context occasionally while processing mutex check results

It's hard to do this remotely sanely for the fragments, but the
translation and collation process itself could be fairly slow on
large data sets, so we should check occasionally for canceled
context and return early if no one needs the result anyway.

Also, take out no-longer-correct comments from the test case.
This commit is contained in:
Seebs 2021-09-08 13:29:55 -05:00
parent 26d38c0ee0
commit e27085da66
2 changed files with 32 additions and 9 deletions

35
api.go
View file

@ -2831,6 +2831,10 @@ func (api *API) MutexCheck(ctx context.Context, qcx *Qcx, indexName string, fiel
}
}
}
// if context is done, return early.
if err := ctx.Err(); err != nil {
return nil, err
}
untranslatedKeys := 0
// Obtain translation tables for the keys.
if useIndexKeys {
@ -2849,6 +2853,10 @@ func (api *API) MutexCheck(ctx context.Context, qcx *Qcx, indexName string, fiel
}
}
}
// if context is done, return early.
if err := ctx.Err(); err != nil {
return nil, err
}
if useFieldKeys {
fieldKeyList, err := api.cluster.translateFieldListIDs(field, fieldIDs)
if err != nil {
@ -2870,6 +2878,11 @@ func (api *API) MutexCheck(ctx context.Context, qcx *Qcx, indexName string, fiel
}
}
// if context is done, return early.
if err := ctx.Err(); err != nil {
return nil, err
}
// define the process functions. separated from above code just to make
// it easier to follow/compare them.
if useIndexKeys {
@ -2879,7 +2892,9 @@ func (api *API) MutexCheck(ctx context.Context, qcx *Qcx, indexName string, fiel
// unlike a map, the slice won't get updated-in-place, so we have
// to assign to result after we're done
defer func() {
result = outStrings
if err == nil {
result = outStrings
}
}()
process = func(recordID uint64, valueIDs []uint64) bool {
if _, ok := outMap[recordID]; ok {
@ -2930,7 +2945,9 @@ func (api *API) MutexCheck(ctx context.Context, qcx *Qcx, indexName string, fiel
// unlike a map, the slice won't get updated-in-place, so we have
// to assign to result after we're done
defer func() {
result = outIDs
if err == nil {
result = outIDs
}
}()
process = func(recordID uint64, valueIDs []uint64) bool {
if _, ok := outMap[recordID]; ok {
@ -2982,18 +2999,30 @@ processing:
if len(nodeResults) == 0 {
continue
}
// if context is done, return early.
if err := ctx.Err(); err != nil {
return nil, err
}
for _, v := range nodeResults {
if len(v) == 0 {
continue
}
counter := 0
for record, values := range v {
counter++
if process(record, values) {
break processing
}
// every 65k items or so, check the context for done-ness
if counter%(1<<16) == 0 {
if err := ctx.Err(); err != nil {
return nil, err
}
}
}
}
}
return result, nil
return result, ctx.Err()
}
type serverInfo struct {

View file

@ -1138,9 +1138,6 @@ func TestAPI_MutexCheck(t *testing.T) {
t.Fatalf("checking mutexes: %v", err)
}
if keyedField {
// this just sorta comes out this way with our hashing; these are
// the things which were in position 1 of their shards, and did
// not have a value which happens to map to 3.
mapped, ok := results.(map[string][]string)
if !ok {
t.Fatalf("expected map[string][]string, got %T", results)
@ -1182,9 +1179,6 @@ func TestAPI_MutexCheck(t *testing.T) {
if err != nil {
t.Fatalf("checking mutexes: %v", err)
}
// this just sorta comes out this way with our hashing; these are
// the things which were in position 1 of their shards, and did
// not have a value which happens to map to 3.
mapped, ok := results.([]string)
if !ok {
t.Fatalf("expected []string, got %T", results)