Created
July 17, 2024 08:08
-
-
Save gotexis/b1d42a4f87eef6a34932b1f2ba0fae9d to your computer and use it in GitHub Desktop.
fetch-queue.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const API_BASE_URL = 'https://api.example.com/deviceOnlineStatus' | |
const API_BEARER_TOKEN = `eyJ0eXAiOiJKadsCJhbGciOiJIy45wNiJ9.eyJpc3MiOiJ5ZWx...` | |
interface DeviceStatus { | |
[deviceId: number]: boolean; | |
} | |
const fetchDeviceStatus = async (deviceId: number, retries: number = 3): Promise<boolean> => { | |
/** | |
* Alloe retries in case of network issues. | |
*/ | |
try { | |
const response = await fetch(`${API_BASE_URL}/${deviceId}`, { | |
method: 'GET', | |
headers: { | |
'Authorization': `Bearer ${API_BEARER_TOKEN}` | |
} | |
}); | |
const text = await response.text(); | |
return text === 'true'; | |
} catch (error) { | |
if (retries > 0) { | |
console.warn(`Retrying request for device ${deviceId}. Remaining retries: ${retries - 1}`); | |
return await fetchDeviceStatus(deviceId, retries - 1); | |
} else { | |
throw new Error(`Failed to fetch status for device ${deviceId} after multiple attempts.`); | |
} | |
} | |
}; | |
/** | |
* Gets the online statuses of the passed devices | |
* @param deviceIds Array of device IDs to check the online status of | |
*/ | |
export async function getDevicesOnlineStatus(deviceIds: number[]): Promise<DeviceStatus> { | |
/** NOTE | |
* this approach doesn't chop requests into smaller arrays with len(5), | |
* it will use a sliding approach to always ensure max concurrency | |
*/ | |
const results: DeviceStatus = {}; | |
const maxConcurrentRequests = 5; | |
let activeRequests = 0; // keeps track of the number of active requests. target should be 5 most of the times | |
let currentIndex = 0; | |
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); | |
const handleNextRequest = async (): Promise<void> => { | |
while (currentIndex < deviceIds.length) { | |
if (activeRequests < maxConcurrentRequests) { | |
activeRequests++; | |
const deviceId = deviceIds[currentIndex++]; | |
// Simulate random delay between 1 and 3 seconds | |
await delay(Math.random() * 2000 + 1000); | |
fetchDeviceStatus(deviceId) | |
.then(status => { | |
results[deviceId] = status; | |
}) | |
.finally(() => { | |
activeRequests--; | |
handleNextRequest(); | |
}); | |
} else { | |
break; | |
} | |
} | |
}; | |
const initialRequests = Math.min(maxConcurrentRequests, deviceIds.length); | |
for (let i = 0; i < initialRequests; i++) { | |
handleNextRequest(); | |
} | |
while (activeRequests > 0 || currentIndex < deviceIds.length) { | |
await delay(50); // Small delay to avoid busy waiting | |
} | |
return results; | |
} | |
// Testing | |
(async () => { | |
const deviceIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; | |
const statuses = await getDevicesOnlineStatus(deviceIds); | |
console.log(statuses); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment