-
Notifications
You must be signed in to change notification settings - Fork 147
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
Added retry mechanism for close contentReader in download. #1099
base: dev
Are you sure you want to change the base?
Conversation
9cbcd6c
to
93fc9b6
Compare
8928ced
to
57749e6
Compare
func (cr *ContentReader) Close() error { | ||
for _, filePath := range cr.filesPaths { | ||
if filePath == "" { | ||
continue | ||
} | ||
if err := errorutils.CheckError(os.Remove(filePath)); err != nil { | ||
// Check if file exists before attempting to remove |
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.
// Check if file exists before attempting to remove | |
func (cr *ContentReader) Close() error { | |
for _, filePath := range cr.filesPaths { | |
if filePath == "" { | |
continue | |
} | |
if err := removeFileWithRetry(filePath); err != nil { | |
return fmt.Errorf("failed to close reader: %w", err) | |
} | |
} | |
cr.filesPaths = nil | |
return nil | |
} | |
func removeFileWithRetry(filePath string) error { | |
// Check if file exists before attempting to remove | |
if _, err := os.Stat(filePath); os.IsNotExist(err) { | |
log.Debug("File does not exist: %s", filePath) | |
return nil | |
} | |
log.Debug("Attempting to remove file: %s", filePath) | |
executor := retryexecutor.RetryExecutor{ | |
Context: context.Background(), | |
MaxRetries: 5, | |
RetriesIntervalMilliSecs: 100, | |
ErrorMessage: "Failed to remove file", | |
LogMsgPrefix: "Attempting removal", | |
ExecutionHandler: func() (bool, error) { | |
return false, errorutils.CheckError(os.Remove(filePath)) | |
}, | |
} | |
return executor.Execute() | |
} |
utils/io/content/contentreader.go
Outdated
func (cr *ContentReader) Close() error { | ||
simulateError := false // Set to true in testing, and false in production |
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.
why do we need this simulate error?
we can simply go ahead and retry
utils/io/content/contentreader.go
Outdated
@@ -93,13 +98,43 @@ func (cr *ContentReader) Reset() { | |||
cr.once = new(sync.Once) | |||
} | |||
|
|||
// Cleanup the reader data. | |||
// Retry function with forced error simulation |
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.
IMO, we should create a general utility function for retry and pass a function along with comparables for the retry operation
utils/io/content/contentreader.go
Outdated
// Simulate an error condition for the first few attempts if `simulateError` is true and attempts are less than maxForcedAttempts | ||
if simulateError && downloadAttempts < maxForcedAttempts { | ||
lastErr = fmt.Errorf("forced error simulation at attempt %d", downloadAttempts+1) | ||
downloadAttempts++ |
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.
why are we referring download here, aren't you just trying to close a opened file?
utils/io/content/contentreader.go
Outdated
log.Info("Operation succeeded at attempt %d", i+1) | ||
return nil | ||
} | ||
log.Warn("Retry attempt %d failed: %v", i+1, lastErr) |
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.
log.Warn("Retry attempt %d failed: %v", i+1, lastErr)
log.Warn("Retry attempt %d failed: %v", i+1, lastErr.Error())
utils/io/content/contentreader.go
Outdated
return nil | ||
} | ||
log.Warn("Retry attempt %d failed: %v", i+1, lastErr) | ||
time.Sleep(time.Millisecond * 100) // Adding a small delay between retries |
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.
why is sleep required?
The changes introduce a refined retry mechanism for simulating and recovering from forced errors encountered during the cleanup of temporary files in the ContentReader's Close method.
Details:
Added Retry Mechanism with Forced Error Simulation:
Controlled Forced Error Simulation: