add ReadFileStream deadline for disk call (#17745)

timeout the reader side if hung via disk max timeout
This commit is contained in:
Harshavardhana
2023-07-28 15:37:53 -07:00
committed by GitHub
parent f9d029c8fa
commit 731e03fe5a
4 changed files with 110 additions and 12 deletions

View File

@@ -73,7 +73,54 @@ type ioret struct {
err error
}
// DeadlineWriter deadline writer with context
// DeadlineReader deadline reader with timeout
type DeadlineReader struct {
io.ReadCloser
timeout time.Duration
err error
}
// NewDeadlineReader wraps a writer to make it respect given deadline
// value per Write(). If there is a blocking write, the returned Reader
// will return whenever the timer hits (the return values are n=0
// and err=context.DeadlineExceeded.)
func NewDeadlineReader(r io.ReadCloser, timeout time.Duration) io.ReadCloser {
return &DeadlineReader{ReadCloser: r, timeout: timeout}
}
func (r *DeadlineReader) Read(buf []byte) (int, error) {
if r.err != nil {
return 0, r.err
}
c := make(chan ioret, 1)
t := time.NewTimer(r.timeout)
go func() {
n, err := r.ReadCloser.Read(buf)
c <- ioret{n, err}
close(c)
}()
select {
case res := <-c:
if !t.Stop() {
<-t.C
}
r.err = res.err
return res.n, res.err
case <-t.C:
r.ReadCloser.Close()
r.err = context.DeadlineExceeded
return 0, context.DeadlineExceeded
}
}
// Close closer interface to close the underlying closer
func (r *DeadlineReader) Close() error {
return r.ReadCloser.Close()
}
// DeadlineWriter deadline writer with timeout
type DeadlineWriter struct {
io.WriteCloser
timeout time.Duration
@@ -119,15 +166,15 @@ func (d *DeadlineWorker) Run(work func() error) error {
d.err = r.err
return r.err
case <-t.C:
d.err = context.Canceled
return context.Canceled
d.err = context.DeadlineExceeded
return context.DeadlineExceeded
}
}
// NewDeadlineWriter wraps a writer to make it respect given deadline
// value per Write(). If there is a blocking write, the returned Writer
// will return whenever the timer hits (the return values are n=0
// and err=context.Canceled.)
// and err=context.DeadlineExceeded.)
func NewDeadlineWriter(w io.WriteCloser, timeout time.Duration) io.WriteCloser {
return &DeadlineWriter{WriteCloser: w, timeout: timeout}
}
@@ -154,8 +201,8 @@ func (w *DeadlineWriter) Write(buf []byte) (int, error) {
return r.n, r.err
case <-t.C:
w.WriteCloser.Close()
w.err = context.Canceled
return 0, context.Canceled
w.err = context.DeadlineExceeded
return 0, context.DeadlineExceeded
}
}