Skip to content

Commit

Permalink
Move areas:save() into async
Browse files Browse the repository at this point in the history
On newer Minetest servers, handles saving jobs in async environment. To prevent conflicts, the save file is locked whie saving, and if a code requests saving while the file is locked, data is saved again immediately after finishing the current save.
  • Loading branch information
Emojigit committed Oct 25, 2024
1 parent 468bb32 commit b87fbe8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 16 deletions.
26 changes: 26 additions & 0 deletions async.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
local areas = {}
local core = core

local safe_file_write = core.safe_file_write
if safe_file_write == nil then
function safe_file_write(path, content)
local file, err = io.open(path, "w")
if err then
return err
end
file:write(content)
file:close()
end
end

-- Save the areas table to a file
function areas:do_save(areas_tb, filename)
local datastr = core.write_json(areas_tb)
if not datastr then
core.log("error", "[areas] Failed to serialize area data!")
return
end
return safe_file_write(filename, datastr)
end

_G.areas = areas
4 changes: 4 additions & 0 deletions init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ dofile(areas.modpath.."/interact.lua")
dofile(areas.modpath.."/legacy.lua")
dofile(areas.modpath.."/hud.lua")

if core.register_async_dofile then
core.register_async_dofile(areas.modpath.."/async.lua")
end

areas:load()

local S = minetest.get_translator("areas")
Expand Down
60 changes: 44 additions & 16 deletions internal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,54 @@ function areas:player_exists(name)
return minetest.get_auth_handler().get_auth(name) ~= nil
end

local safe_file_write = minetest.safe_file_write
if safe_file_write == nil then
function safe_file_write(path, content)
local file, err = io.open(path, "w")
if err then
return err
if core.register_async_dofile then
-- nil: not locked nor requested to save again
-- false: locked and no request for saving again
-- true: locked and will save again on releasing
local file_lock = nil

local function async_func(areas_tb, filepath)
return areas:do_save(areas_tb, filepath)
end

local function done_callback()
local old_lock = file_lock
file_lock = nil
if old_lock == true then
return areas:save()
end
file:write(content)
file:close()
end
end

-- Save the areas table to a file
function areas:save()
local datastr = minetest.write_json(self.areas)
if not datastr then
minetest.log("error", "[areas] Failed to serialize area data!")
return
function areas:save()
if file_lock == false then
file_lock = true
elseif file_lock == nil then
file_lock = false
return core.handle_async(async_func, done_callback, self.areas, self.config.filename)
end
end
else
local safe_file_write = minetest.safe_file_write
if safe_file_write == nil then
function safe_file_write(path, content)
local file, err = io.open(path, "w")
if err then
return err
end
file:write(content)
file:close()
end
end

-- Save the areas table to a file
function areas:save()
local datastr = minetest.write_json(self.areas)
if not datastr then
minetest.log("error", "[areas] Failed to serialize area data!")
return
end
return safe_file_write(self.config.filename, datastr)
end
return safe_file_write(self.config.filename, datastr)
end

-- Load the areas table from the save file
Expand Down

0 comments on commit b87fbe8

Please sign in to comment.