@bigfishtv/cockpit
Version:
71 lines (60 loc) • 2.32 kB
JavaScript
/**
* @module Reducers/imageRequestQueue
*/
import {
ENABLE_IMAGE_REQUEST_QUEUE,
DISABLE_IMAGE_REQUEST_QUEUE,
REQUEST_GENERATED_IMAGE,
CANCEL_GENERATED_IMAGE_REQUEST,
GENERATED_IMAGE_REQUEST_FULFILLED,
} from '../constants/ActionTypes'
const MAX_ACTIVE_REQUESTS = 25
const IMAGE_REQUEST_QUEUE_INTERVAL = 50 // ms
const IMAGE_REQUEST_INITIAL_DELAY = 250 // ms
const IMAGE_REQUEST_TIMEOUT = 5000 // ms
const initialState = { queue: [], enabled: false }
let queue = []
let pendingAssets = 0
const processQueue = () => {
if (!queue.length) return
// filter out unresolved requests older than 5 seconds
const prePurgeCount = queue.length
queue = queue.filter(({ created }) => Date.now() - created < IMAGE_REQUEST_TIMEOUT)
const purgeCount = prePurgeCount - queue.length
pendingAssets -= purgeCount
// if (purgeCount) console.log('Purged ' + purgeCount + ' requests from the queue')
// Recheck queue length after oldie purge
if (!queue.length) return
// Active requests at max, leave it for a tick
if (pendingAssets > MAX_ACTIVE_REQUESTS) return
// Check if request is too young to be considered yet
const actionAge = Date.now() - queue[0].created
if (actionAge < IMAGE_REQUEST_INITIAL_DELAY) return
const action = queue.shift()
if (action.callback) {
// console.log('🏁 allowing this asset', action.key)
action.callback(action.url)
pendingAssets++
}
}
setInterval(processQueue, IMAGE_REQUEST_QUEUE_INTERVAL)
export default function(state = initialState, action) {
switch (action.type) {
case ENABLE_IMAGE_REQUEST_QUEUE:
return { ...state, enabled: true }
case DISABLE_IMAGE_REQUEST_QUEUE:
return { ...state, enabled: false }
case REQUEST_GENERATED_IMAGE:
if (state.enabled) queue.push({ ...action, created: Date.now() })
else action.callback(action.url)
return { ...state, queue }
case GENERATED_IMAGE_REQUEST_FULFILLED:
case CANCEL_GENERATED_IMAGE_REQUEST:
// if (action.type === GENERATED_IMAGE_REQUEST_FULFILLED) console.log('✅ asset request completed', action.key)
// if (action.type === CANCEL_GENERATED_IMAGE_REQUEST) console.log('🗑 cancel loading of this asset', action.key)
pendingAssets--
if (state.enabled) queue = queue.filter(item => item.callback !== action.callback)
return { ...state, queue }
}
return { ...state, queue }
}