Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-05-04 15:51:49 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-05-09 10:30:47 +0300
commit8773480fd0eb9740c96f32e992697600477a5b63 (patch)
treee57a82dfb683f59a9fabc0752453bf2e247dfaa0
parent60b977838c56c120a4cb844392cd304e09510250 (diff)
gitpipe: Propagate context cancellation in object data pipeline
When the context gets cancelled while we're iterating over results from the object data pipeline, then the iterator doesn't return the context cancellation error to the caller when calling `iter.Err()`. It is thus easy to assume at the calling side that the iterator has just finished successfully and that there are no more results, while in reality we only got a partial set of results. Fix this issue by propagating context cancellation errors to the caller. This fixes RPCs based on this pipeline to not return `OK` when there indeed was an error. Changelog: fixed
-rw-r--r--internal/git/gitpipe/catfile_object.go3
-rw-r--r--internal/git/gitpipe/catfile_object_iterator.go38
-rw-r--r--internal/git/gitpipe/catfile_object_test.go7
-rw-r--r--internal/git/gitpipe/pipeline_test.go2
4 files changed, 38 insertions, 12 deletions
diff --git a/internal/git/gitpipe/catfile_object.go b/internal/git/gitpipe/catfile_object.go
index a393ed2ae..f23496158 100644
--- a/internal/git/gitpipe/catfile_object.go
+++ b/internal/git/gitpipe/catfile_object.go
@@ -168,7 +168,8 @@ func CatfileObject(
}()
return &catfileObjectIterator{
- ch: resultChan,
+ ctx: ctx,
+ ch: resultChan,
}, nil
}
diff --git a/internal/git/gitpipe/catfile_object_iterator.go b/internal/git/gitpipe/catfile_object_iterator.go
index c457088e0..05b00e3e8 100644
--- a/internal/git/gitpipe/catfile_object_iterator.go
+++ b/internal/git/gitpipe/catfile_object_iterator.go
@@ -1,6 +1,10 @@
package gitpipe
-import "gitlab.com/gitlab-org/gitaly/v14/internal/git"
+import (
+ "context"
+
+ "gitlab.com/gitlab-org/gitaly/v14/internal/git"
+)
// CatfileObjectIterator is an iterator returned by the Revlist function.
type CatfileObjectIterator interface {
@@ -10,7 +14,7 @@ type CatfileObjectIterator interface {
}
// NewCatfileObjectIterator returns a new CatfileObjectIterator for the given items.
-func NewCatfileObjectIterator(items []CatfileObjectResult) CatfileObjectIterator {
+func NewCatfileObjectIterator(ctx context.Context, items []CatfileObjectResult) CatfileObjectIterator {
itemChan := make(chan CatfileObjectResult, len(items))
for _, item := range items {
itemChan <- item
@@ -18,11 +22,13 @@ func NewCatfileObjectIterator(items []CatfileObjectResult) CatfileObjectIterator
close(itemChan)
return &catfileObjectIterator{
- ch: itemChan,
+ ctx: ctx,
+ ch: itemChan,
}
}
type catfileObjectIterator struct {
+ ctx context.Context
ch <-chan CatfileObjectResult
result CatfileObjectResult
}
@@ -32,13 +38,31 @@ func (it *catfileObjectIterator) Next() bool {
return false
}
- var ok bool
- it.result, ok = <-it.ch
- if !ok || it.result.err != nil {
+ // Prioritize context cancellation errors so that we don't try to fetch results anymore when
+ // the context is done.
+ select {
+ case <-it.ctx.Done():
+ it.result = CatfileObjectResult{err: it.ctx.Err()}
return false
+ default:
}
- return true
+ select {
+ case <-it.ctx.Done():
+ it.result = CatfileObjectResult{err: it.ctx.Err()}
+ return false
+ case result, ok := <-it.ch:
+ if !ok {
+ return false
+ }
+
+ it.result = result
+ if result.err != nil {
+ return false
+ }
+
+ return true
+ }
}
func (it *catfileObjectIterator) Err() error {
diff --git a/internal/git/gitpipe/catfile_object_test.go b/internal/git/gitpipe/catfile_object_test.go
index 17f07f1f8..bf96a19e0 100644
--- a/internal/git/gitpipe/catfile_object_test.go
+++ b/internal/git/gitpipe/catfile_object_test.go
@@ -144,8 +144,9 @@ func TestCatfileObject(t *testing.T) {
cancel()
require.False(t, it.Next())
- // This is a bug: we expect to get the cancelled context here.
- require.NoError(t, it.Err())
- require.Equal(t, CatfileObjectResult{}, it.Result())
+ require.Equal(t, context.Canceled, it.Err())
+ require.Equal(t, CatfileObjectResult{
+ err: context.Canceled,
+ }, it.Result())
})
}
diff --git a/internal/git/gitpipe/pipeline_test.go b/internal/git/gitpipe/pipeline_test.go
index 544ad552d..3d34db488 100644
--- a/internal/git/gitpipe/pipeline_test.go
+++ b/internal/git/gitpipe/pipeline_test.go
@@ -310,7 +310,7 @@ func TestPipeline_revlist(t *testing.T) {
}
}
- require.NoError(t, catfileObjectIter.Err())
+ require.Equal(t, context.Canceled, catfileObjectIter.Err())
// Context cancellation is timing sensitive: at the point of cancelling the context,
// the last pipeline step may already have queued up an additional result. We thus