Skip to content

Instantly share code, notes, and snippets.

@gotexis
Created July 17, 2024 08:08
Show Gist options
  • Save gotexis/b1d42a4f87eef6a34932b1f2ba0fae9d to your computer and use it in GitHub Desktop.
Save gotexis/b1d42a4f87eef6a34932b1f2ba0fae9d to your computer and use it in GitHub Desktop.
fetch-queue.ts
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