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
Add new Atomic File Operations rule #898
Conversation
c9310ef
to
ae3426d
Compare
ae3426d
to
380aacc
Compare
380aacc
to
c98d3cf
Compare
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.
Thank you!
README.adoc
Outdated
# bad | ||
unless Dir.exist?(path) | ||
FileUtils.mkdir(path) | ||
end | ||
|
||
if File.exist?(path) | ||
FileUtils.remove(path) | ||
end |
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.
It may be understood that those two snippets belong to a single example, while those are two separate ones and put corresponding good examples closer to bad ones.
WDYT of:
# bad - race condition with another process may result in an error in `mkdir`
unless Dir.exist?(path)
FileUtils.mkdir(path)
end
# good - atomic and idempotent creation
FileUtils.mkdir_p(path)
# bad - race condition with another process may result in an error in `remove`
if File.exist?(path)
FileUtils.remove(path)
end
# good - atomic and idempotent removal
FileUtils.rm_f(path)
The above addresses two problems:
- Confusion with what the example is
- Order of good and bad
Leaving the order (bad, bad, good, good vs bad, good, bad, good) up to you. I found one example of the second kind of ordering, but pretty sure one could find examples of bad, bad, good, good, too. So it's subjective and I leave it to your judgement how you want to do it.
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.
I was conforming to the nearby good/bad case style, but it may indeed be confusing in a case like this.
I thought the bad, good, bad, good order you gave as an example looked good and I'll rewrite it. Thank you so much.
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.
I indeed like the explanation of what concurrency issue can arise, maybe even specify the errors that could happen: already exists
for mkdir
and does not exist
for remove
?
When doing file operations after confirming the existence check of a file, frequent parallel file operations may cause problems that are difficult to reproduce. Therefore, it is preferable to use atomic file operations. ```ruby # bad - race condition with another process may result in an error in `mkdir` unless Dir.exist?(path) FileUtils.mkdir(path) end # good - atomic and idempotent creation FileUtils.mkdir_p(path) # bad - race condition with another process may result in an error in `remove` if File.exist?(path) FileUtils.remove(path) end # good - atomic and idempotent removal FileUtils.rm_f(path) ```
c98d3cf
to
67cbf7f
Compare
Follow: rubocop/rubocop#10696
When doing file operations after confirming the existence check of a file, frequent parallel file operations may cause problems that are difficult to reproduce.
Therefore, it is preferable to use atomic file operations.