rojo/plugin/src/ChangeBatcher/init.lua
Joe 6dc8f219bd Enhance logging for syncback operations and patch applications
- Added detailed logging for syncback operations, including additions, removals, and updates, to improve traceability and debugging.
- Implemented summary logs for patch applications in both the client and server, capturing the number of changes made.
- Enhanced logging in the ChangeBatcher and ApiService to provide insights into property changes and instance updates during syncback processes.
- Improved error handling and logging for VFS events to ensure better visibility of file operations.
2026-01-31 12:06:27 -06:00

125 lines
2.8 KiB
Lua

--[[
The ChangeBatcher is responsible for collecting and dispatching changes made
to tracked instances during two-way sync.
]]
local RunService = game:GetService("RunService")
local Packages = script.Parent.Parent.Packages
local Log = require(Packages.Log)
local PatchSet = require(script.Parent.PatchSet)
local createPatchSet = require(script.createPatchSet)
local ChangeBatcher = {}
ChangeBatcher.__index = ChangeBatcher
local BATCH_INTERVAL = 0.2
function ChangeBatcher.new(instanceMap, onChangesFlushed)
local self
local renderSteppedConnection = RunService.RenderStepped:Connect(function(dt)
self:__cycle(dt)
end)
self = setmetatable({
__accumulator = 0,
__renderSteppedConnection = renderSteppedConnection,
__instanceMap = instanceMap,
__onChangesFlushed = onChangesFlushed,
__pendingPropertyChanges = {},
__syncSourceOnly = false,
__paused = false,
}, ChangeBatcher)
return self
end
function ChangeBatcher:setSyncSourceOnly(enabled)
self.__syncSourceOnly = enabled
end
-- Pause the batcher to prevent change accumulation during confirmation
function ChangeBatcher:pause()
self.__paused = true
end
-- Resume the batcher after confirmation
function ChangeBatcher:resume()
self.__paused = false
end
-- Check if the batcher is paused
function ChangeBatcher:isPaused()
return self.__paused
end
function ChangeBatcher:stop()
self.__renderSteppedConnection:Disconnect()
self.__pendingPropertyChanges = {}
end
function ChangeBatcher:add(instance, propertyName)
local properties = self.__pendingPropertyChanges[instance]
if not properties then
properties = {}
self.__pendingPropertyChanges[instance] = properties
Log.trace("ChangeBatcher: tracking changes to {}", instance:GetFullName())
end
Log.trace("ChangeBatcher: property '{}' changed on {}", propertyName, instance:GetFullName())
properties[propertyName] = true
end
function ChangeBatcher:__cycle(dt)
-- Skip processing when paused (during confirmation dialogue)
if self.__paused then
return
end
self.__accumulator += dt
if self.__accumulator >= BATCH_INTERVAL then
self.__accumulator -= BATCH_INTERVAL
local patch = self:__flush()
if patch then
self.__onChangesFlushed(patch)
end
end
self.__instanceMap:unpauseAllInstances()
end
function ChangeBatcher:__flush()
if next(self.__pendingPropertyChanges) == nil then
return nil
end
local patch = createPatchSet(self.__instanceMap, self.__pendingPropertyChanges, self.__syncSourceOnly)
self.__pendingPropertyChanges = {}
if PatchSet.isEmpty(patch) then
return nil
end
-- Log summary at debug level
local addedCount = 0
for _ in pairs(patch.added) do
addedCount += 1
end
Log.debug(
"Two-way sync: {} updates, {} additions, {} removals",
#patch.updated,
addedCount,
#patch.removed
)
return patch
end
return ChangeBatcher