Select a file to view its content
Retry with exponential backoff
async function retry<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
const delay = baseDelay * Math.pow(2, i);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error('Unreachable');
}Batch async operations with concurrency limit
async function batchAsync<T, R>(
items: T[],
fn: (item: T) => Promise<R>,
concurrency = 5
): Promise<R[]> {
const results: R[] = [];
const executing: Promise<void>[] = [];
for (const item of items) {
const p = fn(item).then(r => { results.push(r); });
executing.push(p);
if (executing.length >= concurrency) {
await Promise.race(executing);
executing.splice(
executing.findIndex(e => e === p), 1
);
}
}
await Promise.all(executing);
return results;
}Deep object diff for state tracking
function deepDiff<T extends object>(
prev: T,
next: T
): Partial<T> {
const diff: any = {};
for (const key of Object.keys(next) as (keyof T)[]) {
const pVal = prev[key], nVal = next[key];
if (pVal === nVal) continue;
if (typeof nVal === 'object' && nVal !== null
&& typeof pVal === 'object' && pVal !== null) {
const nested = deepDiff(pVal as any, nVal as any);
if (Object.keys(nested).length > 0) {
diff[key] = nested;
}
} else {
diff[key] = nVal;
}
}
return diff;
}LRU Cache with TTL support
class LRUCache<K, V> {
private cache = new Map<K, { value: V; exp: number }>();
constructor(
private maxSize: number,
private ttl: number
) {}
get(key: K): V | undefined {
const item = this.cache.get(key);
if (!item || Date.now() > item.exp) {
this.cache.delete(key);
return undefined;
}
this.cache.delete(key);
this.cache.set(key, item); // Move to end
return item.value;
}
set(key: K, value: V): void {
if (this.cache.size >= this.maxSize) {
const first = this.cache.keys().next().value;
this.cache.delete(first);
}
this.cache.set(key, { value, exp: Date.now() + this.ttl });
}
}