Skip to content

Commit 5bbfef6

Browse files
Make write_env_usage atomic (#2661)
Fixes #2633
1 parent baec70b commit 5bbfef6

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

src/Types.jl

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,15 +463,50 @@ function write_env_usage(source_file::AbstractString, usage_filepath::AbstractSt
463463
# Ensure that log dir exists
464464
!ispath(logdir()) && mkpath(logdir())
465465

466-
# Generate entire entry as a string first
467-
entry = sprint() do io
468-
TOML.print(io, Dict(source_file => [Dict("time" => now())]))
469-
end
470-
471-
# Append entry to log file in one chunk
472466
usage_file = joinpath(logdir(), usage_filepath)
473-
open(usage_file, append=true) do io
474-
write(io, entry)
467+
timestamp = now()
468+
469+
## Atomically write usage file
470+
while true
471+
# read existing usage file
472+
usage = if isfile(usage_file)
473+
TOML.parsefile(usage_file)
474+
else
475+
Dict{String, Any}()
476+
end
477+
478+
# record new usage
479+
usage[source_file] = [Dict("time" => timestamp)]
480+
481+
# keep only latest usage info
482+
for k in keys(usage)
483+
times = map(d -> Dates.DateTime(d["time"]), usage[k])
484+
usage[k] = [Dict("time" => maximum(times))]
485+
end
486+
487+
# Write to a temp file in the same directory as the destination
488+
temp_usage_file = tempname(logdir())
489+
open(temp_usage_file, "w") do io
490+
TOML.print(io, usage, sorted=true)
491+
end
492+
493+
# Move the temp file into place, replacing the original
494+
mv(temp_usage_file, usage_file, force = true)
495+
496+
# Check that the new file has what we want in it
497+
new_usage = if isfile(usage_file)
498+
TOML.parsefile(usage_file)
499+
else
500+
Dict{String, Any}()
501+
end
502+
if haskey(new_usage, source_file)
503+
for e in new_usage[source_file]
504+
if Dates.DateTime(e["time"]) >= timestamp
505+
return
506+
end
507+
end
508+
end
509+
# If not, try again
475510
end
476511
end
477512

0 commit comments

Comments
 (0)