MCPcopy Create free account
hub / github.com/imgproxy/imgproxy / readChunks

Method readChunks

asyncbuffer/buffer.go:343–424  ·  view source on GitHub ↗

readChunks reads data from the upstream reader in background and stores them in the pool

()

Source from the content-addressed store, hash-verified

341
342// readChunks reads data from the upstream reader in background and stores them in the pool
343func (ab *AsyncBuffer) readChunks() {
344 defer func() {
345 if ab.bytesRead.Load() < int64(ab.dataLen) {
346 // If the reader has finished reading and we have not read enough data,
347 // set err to io.ErrUnexpectedEOF
348 ab.setErr(io.ErrUnexpectedEOF)
349 }
350
351 // Indicate that the reader has finished reading
352 ab.finished.Store(true)
353 ab.chunkCond.Close()
354
355 // Close the upstream reader
356 if err := ab.r.Close(); err != nil {
357 slog.Warn(
358 "error closing upstream reader",
359 "error", err,
360 "source", "asyncbuffer.AsyncBuffer.readChunks",
361 )
362 }
363
364 ab.callFinishFn()
365 }()
366
367 r := ab.r.(io.Reader) //nolint:forcetypeassert
368 if ab.dataLen > 0 {
369 // If the data length is known, we read only that much data
370 r = io.LimitReader(r, int64(ab.dataLen))
371 }
372
373 // Stop reading if the reader is closed
374 for !ab.closed.Load() {
375 // In case we are trying to read data beyond threshold and we are paused,
376 // wait for pause to be released.
377 if ab.bytesRead.Load() >= PauseThreshold {
378 ab.paused.Wait()
379
380 // If the reader has been closed while waiting, we can stop reading
381 if ab.closed.Load() {
382 return // No more data to read
383 }
384 }
385
386 // Get a chunk from the pool
387 // If the pool is empty, it will create a new byteChunk with ChunkSize
388 chunk, ok := chunkPool.Get().(*byteChunk)
389 if !ok {
390 ab.setErr(errors.New("asyncbuffer.AsyncBuffer.readChunks: failed to get chunk from pool"))
391 return
392 }
393
394 // Read data into the chunk's buffer
395 // There is no way to guarantee that r.Read will abort on context cancellation,
396 // unfortunately, this is how golang works.
397 n, err := ioutil.TryReadFull(r, chunk.buf)
398
399 // If it's not the EOF, we need to store the error
400 if err != nil && !errors.Is(err, io.EOF) {

Callers 2

NewFunction · 0.95
NewReadFullFunction · 0.95

Calls 9

setErrMethod · 0.95
callFinishFnMethod · 0.95
addChunkMethod · 0.95
TryReadFullFunction · 0.92
LoadMethod · 0.80
WarnMethod · 0.80
CloseMethod · 0.65
GetMethod · 0.65
WaitMethod · 0.45

Tested by

no test coverage detected