From c8089109c6addf76291fc9dbbb15018b847a9b09 Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Sun, 14 Sep 2025 15:18:36 +0100 Subject: [PATCH] Add "await" for callbacks This hopefully should help callbacks get their requested data Basically gives them a timeout for requests, so they don't accidently receive `nil` --- shared/callback.lua | 103 +++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 26 deletions(-) diff --git a/shared/callback.lua b/shared/callback.lua index b6ad9d6..cb59fe6 100644 --- a/shared/callback.lua +++ b/shared/callback.lua @@ -1,3 +1,31 @@ +local CALLBACK_RETRIES = 0 + +-- Internal: await a callback with a timeout +local function awaitWithTimeout(registerFn, timeoutMs) + local p = promise.new() + local finished = false + + registerFn(function(result) + if finished then return end + finished = true + p:resolve(result) + end) + + -- timeout watchdog + CreateThread(function() + Wait(5000) + if not finished then + finished = true + p:reject('timeout') + end + end) + + local ok, res = pcall(function() return Citizen.Await(p) end) + if ok then return res, nil end + return nil, res +end + + --- Registers a callback function with the appropriate framework. --- --- This function checks which framework is started (e.g., OX, QB, ESX) and registers the callback accordingly. @@ -59,6 +87,7 @@ end ---@param ... any Additional arguments to pass to the callback. --- ---@return any any The result returned by the callback function. +---@return string string The error/success message returned by the callback function. --- ---@usage --- ```lua @@ -69,32 +98,54 @@ end --- print(result) --- ``` function triggerCallback(callbackName, ...) - local result = nil debugPrint("^6Bridge^7: ^2Triggering ^3Callback^7:", callbackName) + local args = {...} + if isStarted(OXLibExport) then - result = lib.callback.await(callbackName, false, ...) - elseif isStarted(QBExport) then - local p = promise.new() - Core.Functions.TriggerCallback(callbackName, function(cbResult) - p:resolve(cbResult) - end, ...) - result = Citizen.Await(p) - Wait(10) - elseif isStarted(VorpExport) then - local p = promise.new() - Core.Callback.TriggerAwait(callbackName, function(cbResult) - p:resolve(cbResult) - end, ...) - result = Citizen.Await(p) - Wait(10) - elseif isStarted(ESXExport) then - local p = promise.new() - ESX.TriggerServerCallback(callbackName, function(cbResult) - p:resolve(cbResult) - end, ...) - result = Citizen.Await(p) - else - print("^6Bridge^7: ^1ERROR^7: ^3Can't find any script to trigger callback with", callbackName) + local ok, res = pcall(function() + return lib.callback.await(callbackName, false, table.unpack(args)) + end) + if ok then return res, "nil" end + return nil, tostring(res) end - return result -end \ No newline at end of file + + local attempts = 0 + local lastErr + + repeat + attempts = attempts + 1 + + if isStarted(QBExport) then + local res, err = awaitWithTimeout(function(cb) + Core.Functions.TriggerCallback(callbackName, cb, table.unpack(args)) + end, 5000) + if res ~= nil then return res, "nil" end + lastErr = err + debugPrint(("^6Bridge^7: ^3Callback^7 %s ^1failed^7 (QB) attempt %d: %s"):format(callbackName, attempts, tostring(err))) + + elseif isStarted(VorpExport) then + local res, err = awaitWithTimeout(function(cb) + Core.Callback.TriggerAwait(callbackName, cb, table.unpack(args)) + end, 5000) + if res ~= nil then return res, "nil" end + lastErr = err + debugPrint(("^6Bridge^7: ^3Callback^7 %s ^1failed^7 (Vorp) attempt %d: %s"):format(callbackName, attempts, tostring(err))) + + elseif isStarted(ESXExport) then + local res, err = awaitWithTimeout(function(cb) + ESX.TriggerServerCallback(callbackName, cb, table.unpack(args)) + end, 5000) + if res ~= nil then return res, "nil" end + lastErr = err + debugPrint(("^6Bridge^7: ^3Callback^7 %s ^1failed^7 (ESX) attempt %d: %s"):format(callbackName, attempts, tostring(err))) + + else + print("^6Bridge^7: ^1ERROR^7: ^3Can't find any script to trigger callback with^7:", callbackName) + return nil, "no_framework" + end + + Wait(10) + until attempts > (1 + CALLBACK_RETRIES) + + return nil, lastErr or "timeout" +end