-
Notifications
You must be signed in to change notification settings - Fork 684
ingest storage: Refactor ConcurrentFetchers.run
#13809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
f0f6d8a
738bb71
bf843f2
2e13d34
4e1d653
17904f0
10a1be5
daf2bc3
ec7e339
127f700
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -689,118 +689,122 @@ func (r *ConcurrentFetchers) run(ctx context.Context, wants chan fetchWant, logg | |||||||||||||
| errBackoff := backoff.New(ctx, r.fetchBackoffConfig) | ||||||||||||||
|
|
||||||||||||||
| for w := range wants { | ||||||||||||||
| // Start new span for each fetchWant. We want to record the lifecycle of a single record from being fetched to being ingested. | ||||||||||||||
| wantSpan, ctx := spanlogger.New(ctx, logger, tracer, "concurrentFetcher.fetch") | ||||||||||||||
| wantSpan.SetTag("start_offset", w.startOffset) | ||||||||||||||
| wantSpan.SetTag("end_offset", w.endOffset) | ||||||||||||||
|
|
||||||||||||||
| // This current buffered fetchResult that has not been sent to the result channel yet. | ||||||||||||||
| // This is empty at the beginning, then we merge records as soon as we receive them | ||||||||||||||
| // from the Fetch response(s). | ||||||||||||||
| var bufferedResult fetchResult | ||||||||||||||
|
|
||||||||||||||
| for attempt := 0; errBackoff.Ongoing() && w.endOffset > w.startOffset; attempt++ { | ||||||||||||||
| attemptSpan, ctx := spanlogger.New(ctx, logger, tracer, "concurrentFetcher.fetch.attempt") | ||||||||||||||
| attemptSpan.SetTag("attempt", attempt) | ||||||||||||||
|
|
||||||||||||||
| // Run a single Fetch request. | ||||||||||||||
| if res := r.fetchSingle(ctx, w); res.Err != nil { | ||||||||||||||
| // We got an error. We handle it and then discard this fetch result content. | ||||||||||||||
| var err error | ||||||||||||||
| w, err = handleKafkaFetchErr(res.Err, w, errBackoff, r.rangeErrorPolicy, r.startOffsetsReader, r.client, attemptSpan) | ||||||||||||||
| if err != nil { | ||||||||||||||
| // An error returned from handleKafkaFetchErr is a fatal | ||||||||||||||
| // error. We produce an error result and abort further | ||||||||||||||
| // processing. | ||||||||||||||
|
|
||||||||||||||
| level.Warn(logger).Log("msg", "failed to handle Kafka fetch error", "error", err) | ||||||||||||||
|
|
||||||||||||||
| select { | ||||||||||||||
| case <-r.done: | ||||||||||||||
| wantSpan.Finish() | ||||||||||||||
| attemptSpan.Finish() | ||||||||||||||
| close(w.result) | ||||||||||||||
| return | ||||||||||||||
| case <-ctx.Done(): | ||||||||||||||
| case w.result <- newErrorFetchResult(ctx, r.partitionID, err): | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Break out of the retry loop, but continue servicing the `wants` channel. | ||||||||||||||
| break | ||||||||||||||
| } | ||||||||||||||
| } else { | ||||||||||||||
| // We increase the count of buffered records as soon as we fetch them. | ||||||||||||||
| r.bufferedFetchedRecords.Add(int64(len(res.Records))) | ||||||||||||||
| r.handleWant(ctx, logger, w, errBackoff, highWatermark) | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // Update the high watermark. | ||||||||||||||
| if hwm := res.HighWatermark; hwm >= 0 { | ||||||||||||||
| casHWM(highWatermark, hwm) | ||||||||||||||
| } | ||||||||||||||
| // handleWant handles a single fetchWant. It performs Fetch requests until the fetchWant is complete or the context is cancelled. | ||||||||||||||
| func (r *ConcurrentFetchers) handleWant(ctx context.Context, logger log.Logger, w fetchWant, errBackoff *backoff.Backoff, highWatermark *atomic.Int64) { | ||||||||||||||
| // Start new span for each fetchWant. We want to record the lifecycle of a single record from being fetched to being ingested. | ||||||||||||||
| wantSpan, ctx := spanlogger.New(ctx, logger, tracer, "concurrentFetcher.fetch") | ||||||||||||||
| wantSpan.SetTag("start_offset", w.startOffset) | ||||||||||||||
| wantSpan.SetTag("end_offset", w.endOffset) | ||||||||||||||
|
|
||||||||||||||
| defer close(w.result) | ||||||||||||||
| defer wantSpan.Finish() | ||||||||||||||
|
|
||||||||||||||
| // This current buffered fetchResult that has not been sent to the result channel yet. | ||||||||||||||
| // This is empty at the beginning, then we merge records as soon as we receive them | ||||||||||||||
| // from the Fetch response(s). | ||||||||||||||
| var bufferedResult fetchResult | ||||||||||||||
|
|
||||||||||||||
| for attempt := 0; errBackoff.Ongoing() && !r.isDone() && w.endOffset > w.startOffset; attempt++ { | ||||||||||||||
| var continueAttempts bool | ||||||||||||||
| w, continueAttempts = r.performAttempt(ctx, logger, attempt, w, errBackoff, highWatermark, bufferedResult) | ||||||||||||||
| if !continueAttempts { | ||||||||||||||
| break | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
||||||||||||||
| } | |
| } | |
| // Send any remaining bufferedResult before exiting. | |
| if len(bufferedResult.Records) > 0 { | |
| w.result <- bufferedResult | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, interesting, I'll think about that.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should every
wantget a freshbackoff?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would different wants get different behaviour from the kafka brokers? i don't think so. if they start getting errors, they slow down faster if they use a single backoff