139 lines
4.6 KiB
Lua
139 lines
4.6 KiB
Lua
local CorePackages = game:GetService("CorePackages")
|
|
local LuaApp = CorePackages.AppTempCommon.LuaApp
|
|
local ArgCheck = require(CorePackages.ArgCheck)
|
|
|
|
local Thumbnail = require(LuaApp.Models.Thumbnail)
|
|
|
|
local PerformFetch = require(LuaApp.Thunks.Networking.Util.PerformFetch)
|
|
local Promise = require(LuaApp.Promise)
|
|
local Result = require(LuaApp.Result)
|
|
|
|
local TableUtilities = require(LuaApp.TableUtilities)
|
|
|
|
local RETRY_MAX_COUNT = math.max(0, settings():GetFVariable("LuaAppNonFinalThumbnailMaxRetries"))
|
|
local RETRY_TIME_MULTIPLIER = math.max(0, settings():GetFVariable("LuaAppThumbnailsApiRetryTimeMultiplier")) -- seconds
|
|
|
|
local FetchSubdividedThumbnails = {}
|
|
|
|
function FetchSubdividedThumbnails._fetchIcons(store, networkImpl, targetIds, iconSize, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
local function keyMapperForCurrentRequestNameAndSize(targetId)
|
|
return keyMapper({
|
|
targetId = targetId,
|
|
requestName = requestName,
|
|
iconSize = iconSize
|
|
})
|
|
end
|
|
|
|
local function getTableOfFailedResults(failedTargetIds)
|
|
local results = {}
|
|
for _, targetId in pairs(failedTargetIds) do
|
|
local key = keyMapperForCurrentRequestNameAndSize(targetId)
|
|
results[key] = Result.new(false, {
|
|
targetId = targetId,
|
|
})
|
|
end
|
|
return results
|
|
end
|
|
|
|
return fetchFunction(networkImpl, targetIds, iconSize):andThen(
|
|
function(result)
|
|
local results = getTableOfFailedResults(targetIds)
|
|
local validIcons = {}
|
|
|
|
local data = result and result.responseBody and result.responseBody.data
|
|
if typeof(data) == "table" then
|
|
for _, iconInfo in pairs(data) do
|
|
if Thumbnail.isCompleteThumbnailData(iconInfo) then
|
|
local targetId = tostring(iconInfo.targetId)
|
|
local success = false
|
|
if Thumbnail.checkStateIsFinal(iconInfo.state) then
|
|
validIcons[targetId] = Thumbnail.fromThumbnailData(iconInfo, iconSize)
|
|
success = true
|
|
end
|
|
results[keyMapperForCurrentRequestNameAndSize(targetId)] = Result.new(success, iconInfo)
|
|
end
|
|
end
|
|
end
|
|
store:dispatch(storeDispatch(validIcons))
|
|
return Promise.resolve(results)
|
|
end,
|
|
function(err)
|
|
local results = getTableOfFailedResults(targetIds)
|
|
return Promise.resolve(results)
|
|
end
|
|
)
|
|
end
|
|
|
|
function FetchSubdividedThumbnails._fetch(store, networkImpl, targetIds, size, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
return FetchSubdividedThumbnails._fetchIcons(store, networkImpl, targetIds, size, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
:andThen(function(results)
|
|
local completedIcons = {}
|
|
local iconResults = results
|
|
|
|
if _G.__TESTEZ_RUNNING_TEST__ then
|
|
RETRY_MAX_COUNT = 1
|
|
RETRY_TIME_MULTIPLIER = 0.001
|
|
end
|
|
|
|
local function retry(retryCount)
|
|
local remainingUnfinalizedIcons = {}
|
|
|
|
for k, result in pairs(iconResults) do
|
|
local isSuccessful, iconInfo = result:unwrap()
|
|
-- Retry icon request for targetId that failed.
|
|
if isSuccessful and Thumbnail.checkStateIsFinal(iconInfo.state) then
|
|
completedIcons[k] = result
|
|
else
|
|
table.insert(remainingUnfinalizedIcons, iconInfo)
|
|
end
|
|
end
|
|
|
|
if TableUtilities.FieldCount(remainingUnfinalizedIcons) == 0 then
|
|
--All requests are successful
|
|
return Promise.resolve(completedIcons)
|
|
end
|
|
|
|
local delayPromise = Promise.new(function(resolve, reject)
|
|
coroutine.wrap(function()
|
|
wait(RETRY_TIME_MULTIPLIER * math.pow(2, retryCount - 1))
|
|
resolve()
|
|
end)()
|
|
end)
|
|
|
|
return delayPromise:andThen(function()
|
|
return FetchSubdividedThumbnails._fetchIcons(store, networkImpl,
|
|
targetIds, size, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
end):andThen(function(newResults)
|
|
iconResults = newResults
|
|
if retryCount > 1 then
|
|
return retry(retryCount - 1)
|
|
else
|
|
return Promise.resolve(completedIcons)
|
|
end
|
|
end)
|
|
end
|
|
|
|
return retry(RETRY_MAX_COUNT)
|
|
end)
|
|
end
|
|
|
|
function FetchSubdividedThumbnails.Fetch(networkImpl, requests, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
ArgCheck.isType(requests, "table", "requests")
|
|
ArgCheck.isType(requestName, "string", "requestName")
|
|
ArgCheck.isNonNegativeNumber(#requests, "requests count")
|
|
|
|
FetchSubdividedThumbnails.KeyMapper = keyMapper
|
|
return PerformFetch.Batch(requests, keyMapper, function(store, filteredrequests)
|
|
local targetIdsNeeded = {}
|
|
local size
|
|
-- Filter out the icons that are already in the store.
|
|
for _, request in ipairs(filteredrequests) do
|
|
local targetId = request.targetId
|
|
size = request.iconSize
|
|
table.insert(targetIdsNeeded, targetId)
|
|
end
|
|
return FetchSubdividedThumbnails._fetch(store, networkImpl, targetIdsNeeded, size, keyMapper, requestName, fetchFunction, storeDispatch)
|
|
end)
|
|
end
|
|
|
|
return FetchSubdividedThumbnails |