Ensure deterministic execution, for tests

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Arve Knudsen 2023-10-20 16:16:10 +02:00
parent 6dcebc9e25
commit efcd876b50
2 changed files with 15 additions and 4 deletions

View file

@ -93,6 +93,11 @@ func (p *postingsForMatcherPromise) result(ctx context.Context) (index.Postings,
case <-ctx.Done():
return nil, ctx.Err()
case <-p.done:
// Checking context error is necessary for deterministic tests,
// as channel selection order is random
if ctx.Err() != nil {
return nil, ctx.Err()
}
if p.err != nil {
return nil, p.err
}
@ -107,12 +112,18 @@ func (c *PostingsForMatchersCache) postingsForMatchersPromise(ix IndexPostingsRe
key := matchersKey(ms)
oldPromise, loaded := c.calls.LoadOrStore(key, promise)
if loaded {
promise = oldPromise.(*postingsForMatcherPromise)
return promise.result
// promise was not stored, we return a previously stored promise, that's possibly being fulfilled in another goroutine
close(promise.done)
return oldPromise.(*postingsForMatcherPromise).result
}
// promise was stored, close its channel after fulfilment
defer close(promise.done)
// FIXME: do we need to cancel the call to postingsForMatchers if all the callers waiting for the result have cancelled their context?
// Don't let context cancellation fail the promise, since it may be used by multiple goroutines, each with
// its own context. Also, keep the call independent of this particular context, since the promise will be reused.
// FIXME: do we need to cancel the call to postingsForMatchers if all the callers waiting for the result have
// cancelled their context?
if postings, err := c.postingsForMatchers(context.Background(), ix, ms...); err != nil {
promise.err = err
} else {

View file

@ -352,7 +352,7 @@ func TestPostingsForMatchersCache(t *testing.T) {
ctx1, cancel := context.WithCancel(context.Background())
cancel()
_, err := c.PostingsForMatchers(ctx1, indexForPostingsMock{}, true, matchers...)
require.Equal(t, context.Canceled, err)
require.ErrorIs(t, err, context.Canceled)
ctx2 := context.Background()
actualPostings, err := c.PostingsForMatchers(ctx2, indexForPostingsMock{}, true, matchers...)