130 lines
3.1 KiB
Lua
130 lines
3.1 KiB
Lua
local CorePackages = game:GetService("CorePackages")
|
|
local RunService = game:GetService("RunService")
|
|
|
|
local Cryo = require(CorePackages.Packages.Cryo)
|
|
local t = require(CorePackages.Packages.t)
|
|
|
|
-- Time limit is in seconds.
|
|
local DEFAULT_QUEUE_TIME_LIMIT = 30
|
|
local DEFAULT_QUEUE_ERROR_LIMIT = 30
|
|
local DEFAULT_QUEUE_KEY_LIMIT = 10
|
|
|
|
local ErrorQueue = {}
|
|
ErrorQueue.__index = ErrorQueue
|
|
|
|
local IErrorQueue = t.tuple(
|
|
t.callback,
|
|
t.optional(t.strictInterface({
|
|
queueTimeLimit = t.optional(t.numberPositive),
|
|
queueErrorLimit = t.optional(t.numberPositive),
|
|
queueKeyLimit = t.optional(t.numberPositive),
|
|
}))
|
|
)
|
|
|
|
function ErrorQueue.new(reportMethod, options)
|
|
assert(IErrorQueue(reportMethod, options))
|
|
|
|
options = options or {}
|
|
|
|
local self = {
|
|
_reportMethod = reportMethod,
|
|
|
|
-- config
|
|
_queueTimeLimit = options.queueTimeLimit or DEFAULT_QUEUE_TIME_LIMIT,
|
|
_queueErrorLimit = options.queueErrorLimit or DEFAULT_QUEUE_ERROR_LIMIT,
|
|
_queueKeyLimit = options.queueKeyLimit or DEFAULT_QUEUE_KEY_LIMIT,
|
|
|
|
_errors = {},
|
|
_totalErrorCount = 0,
|
|
_totalKeyCount = 0,
|
|
|
|
_runningTime = 0,
|
|
_renderSteppedConnection = nil,
|
|
}
|
|
|
|
setmetatable(self, ErrorQueue)
|
|
|
|
return self
|
|
end
|
|
|
|
function ErrorQueue:hasError(errorKey)
|
|
if type(errorKey) ~= "string" or errorKey == "" then
|
|
return false
|
|
else
|
|
return self._errors[errorKey] ~= nil
|
|
end
|
|
end
|
|
|
|
function ErrorQueue:addError(errorKey, errorData)
|
|
if type(errorKey) ~= "string" or errorKey == "" then
|
|
return
|
|
end
|
|
|
|
if not self._errors[errorKey] then
|
|
-- Errors with the same key will be sent together as 1 error, with a count parameter.
|
|
-- We only keep the data from the oldest error with this key in the queue.
|
|
self._errors[errorKey] = {
|
|
data = errorData,
|
|
count = 1,
|
|
}
|
|
self._totalKeyCount = self._totalKeyCount + 1
|
|
else
|
|
self._errors[errorKey].count = self._errors[errorKey].count + 1
|
|
end
|
|
|
|
self._totalErrorCount = self._totalErrorCount + 1
|
|
|
|
if self:isReadyToReport() then
|
|
self:reportAllErrors()
|
|
end
|
|
end
|
|
|
|
function ErrorQueue:isReadyToReport()
|
|
return self._totalKeyCount >= self._queueKeyLimit or
|
|
self._totalErrorCount >= self._queueErrorLimit or
|
|
(self._totalErrorCount > 0 and self._runningTime >= self._queueTimeLimit)
|
|
end
|
|
|
|
function ErrorQueue:reportAllErrors()
|
|
-- copy the error queue and instantly clear it out
|
|
local errors = Cryo.Dictionary.join(self._errors, {})
|
|
|
|
self._errors = {}
|
|
self._totalErrorCount = 0
|
|
self._totalKeyCount = 0
|
|
self._runningTime = 0
|
|
|
|
-- report the errors
|
|
for errorKey, errData in pairs(errors) do
|
|
self._reportMethod(errorKey, errData.data, errData.count)
|
|
end
|
|
end
|
|
|
|
function ErrorQueue:_onRenderStep(dt)
|
|
self._runningTime = self._runningTime + dt
|
|
|
|
if self:isReadyToReport() then
|
|
self:reportAllErrors()
|
|
end
|
|
end
|
|
|
|
function ErrorQueue:startTimer()
|
|
if self._renderSteppedConnection == nil then
|
|
self._runningTime = 0
|
|
|
|
self._renderSteppedConnection = RunService.renderStepped:Connect(function(dt)
|
|
self:_onRenderStep(dt)
|
|
end)
|
|
end
|
|
end
|
|
|
|
function ErrorQueue:stopTimer()
|
|
if self._renderSteppedConnection ~= nil then
|
|
self._renderSteppedConnection:Disconnect()
|
|
self._runningTime = 0
|
|
self._renderSteppedConnection = nil
|
|
end
|
|
end
|
|
|
|
return ErrorQueue
|