UNPKG

@comic-vine/in-memory-store

Version:

In-memory store implementations for Comic Vine client caching, deduplication, and rate limiting

1 lines 49.4 kB
{"version":3,"sources":["../src/in-memory-cache-store.ts","../src/in-memory-dedupe-store.ts","../src/in-memory-rate-limit-store.ts","../src/adaptive-rate-limit-store.ts"],"names":["safeStringify","randomUUID","DEFAULT_RATE_LIMIT","AdaptiveCapacityCalculator"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { CacheStore } from '@comic-vine/client';\n// We use fast-safe-stringify instead of JSON.stringify so that\n// 1) objects containing circular references don’t throw, and\n// 2) we get a deterministic string length for accurate memory-usage\n// calculations. A normal JSON.stringify would either error or\n// force us to fallback to a rough 1 KB estimate, under-reporting\n// large cyclic payloads.\nimport safeStringify from 'fast-safe-stringify';\n\ninterface CacheItem<T> {\n value: T;\n expiresAt: number;\n lastAccessed: number;\n size: number; // bytes occupied by this entry\n}\n\nexport interface InMemoryCacheStoreOptions {\n /** Cleanup interval in milliseconds. Set to 0 to disable automatic cleanup. Default: 60000 (1 minute) */\n cleanupIntervalMs?: number;\n /** Maximum number of items to store. When exceeded, least recently used items are evicted. Default: 1000 */\n maxItems?: number;\n /** Maximum memory usage in bytes (rough estimate). When exceeded, least recently used items are evicted. Default: 50MB */\n maxMemoryBytes?: number;\n /** When evicting items, remove this percentage of LRU items. Default: 0.1 (10%) */\n evictionRatio?: number;\n}\n\nexport class InMemoryCacheStore<T = unknown> implements CacheStore<T> {\n private cache = new Map<string, CacheItem<T>>();\n private cleanupInterval?: NodeJS.Timeout;\n private readonly maxItems: number;\n private readonly maxMemoryBytes: number;\n private readonly evictionRatio: number;\n private totalSize = 0; // running total of memory usage in bytes\n\n constructor(options: InMemoryCacheStoreOptions = {}) {\n const cleanupIntervalMs = options.cleanupIntervalMs ?? 60000; // 1 minute default\n this.maxItems = options.maxItems ?? 1000;\n this.maxMemoryBytes = options.maxMemoryBytes ?? 50 * 1024 * 1024; // 50MB default\n this.evictionRatio = options.evictionRatio ?? 0.1;\n\n if (cleanupIntervalMs > 0) {\n this.cleanupInterval = setInterval(() => {\n this.cleanup();\n }, cleanupIntervalMs);\n // Allow the Node.js process to exit naturally if this timer is the only event loop item\n if (typeof this.cleanupInterval.unref === 'function') {\n this.cleanupInterval.unref();\n }\n }\n }\n\n async get(hash: string): Promise<T | undefined> {\n const item = this.cache.get(hash);\n\n if (!item || (item.expiresAt > 0 && Date.now() > item.expiresAt)) {\n this.cache.delete(hash);\n return undefined;\n }\n\n // Update last accessed time for LRU\n item.lastAccessed = Date.now();\n // Re-set the item to trigger map ordering update\n this.cache.set(hash, item);\n return item.value;\n }\n\n async set(hash: string, value: T, ttlSeconds: number): Promise<void> {\n const now = Date.now();\n const expiresAt = ttlSeconds === 0 ? 0 : now + ttlSeconds * 1000;\n\n // If replacing an existing entry, subtract its size first\n const existing = this.cache.get(hash);\n if (existing) {\n this.totalSize -= existing.size;\n }\n\n const entrySize = this.estimateEntrySize(hash, value);\n this.totalSize += entrySize;\n\n this.cache.set(hash, {\n value,\n expiresAt,\n lastAccessed: now,\n size: entrySize,\n });\n\n // Check if we need to evict items\n this.enforceMemoryLimits();\n }\n\n async delete(hash: string): Promise<void> {\n const existing = this.cache.get(hash);\n if (existing) {\n this.totalSize -= existing.size;\n }\n this.cache.delete(hash);\n }\n\n async clear(): Promise<void> {\n this.cache.clear();\n this.totalSize = 0;\n }\n\n /**\n * Get statistics about cache usage\n */\n getStats(): {\n totalItems: number;\n expired: number;\n memoryUsageBytes: number;\n maxItems: number;\n maxMemoryBytes: number;\n memoryUtilization: number;\n itemUtilization: number;\n } {\n const now = Date.now();\n let expired = 0;\n\n for (const [_hash, item] of this.cache) {\n if (item.expiresAt > 0 && now > item.expiresAt) {\n expired++;\n }\n }\n\n // Rough estimate of memory usage\n const memoryUsageBytes = this.calculateMemoryUsage();\n\n return {\n totalItems: this.cache.size,\n expired,\n memoryUsageBytes,\n maxItems: this.maxItems,\n maxMemoryBytes: this.maxMemoryBytes,\n memoryUtilization: memoryUsageBytes / this.maxMemoryBytes,\n itemUtilization: this.cache.size / this.maxItems,\n };\n }\n\n /**\n * Clean up expired cache entries\n */\n cleanup(): void {\n const now = Date.now();\n const toDelete: Array<string> = [];\n\n for (const [hash, item] of this.cache) {\n if (item.expiresAt > 0 && now > item.expiresAt) {\n toDelete.push(hash);\n }\n }\n\n for (const hash of toDelete) {\n const item = this.cache.get(hash);\n if (item) {\n this.totalSize -= item.size;\n }\n this.cache.delete(hash);\n }\n }\n\n /**\n * Enforce memory and item count limits using LRU eviction\n */\n private enforceMemoryLimits(): void {\n // Check item count limit\n if (this.cache.size > this.maxItems) {\n this.evictLRUItems(this.cache.size - this.maxItems);\n return;\n }\n\n // Check memory usage limit\n const memoryUsage = this.totalSize;\n if (memoryUsage > this.maxMemoryBytes) {\n const itemsToEvict = Math.max(\n 1,\n Math.floor(this.cache.size * this.evictionRatio),\n );\n this.evictLRUItems(itemsToEvict);\n }\n }\n\n /**\n * Evict the least recently used items\n */\n private evictLRUItems(count: number): void {\n // Sort entries by last accessed time (oldest first)\n const entries = Array.from(this.cache.entries()).sort(\n ([, a], [, b]) => a.lastAccessed - b.lastAccessed,\n );\n\n // Remove the oldest entries\n for (let i = 0; i < count && i < entries.length; i++) {\n const entry = entries[i];\n if (entry) {\n const [key, item] = entry;\n this.totalSize -= item.size;\n this.cache.delete(key);\n }\n }\n }\n\n /**\n * Calculate rough memory usage\n */\n private calculateMemoryUsage(): number {\n // O(1) – maintained incrementally\n return this.totalSize;\n }\n\n /**\n * Get items sorted by last accessed time (for debugging/monitoring)\n */\n getLRUItems(\n limit: number = 10,\n ): Array<{ hash: string; lastAccessed: Date; size: number }> {\n const entries = Array.from(this.cache.entries())\n .sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed)\n .slice(0, limit);\n\n return entries.map(([hash, item]) => ({\n hash,\n lastAccessed: new Date(item.lastAccessed),\n size: item.size,\n }));\n }\n\n /**\n * Destroy the cache and cleanup resources\n */\n destroy(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = undefined;\n }\n this.cache.clear();\n this.totalSize = 0;\n }\n\n /**\n * Estimate the size in bytes of a cache entry (key + value + metadata)\n */\n private estimateEntrySize(hash: string, value: unknown): number {\n let size = 0;\n\n // Hash key size (UTF-16 => 2 bytes per char)\n size += hash.length * 2;\n\n // Metadata size (expiresAt & lastAccessed)\n size += 16;\n\n // Value size via safe-stringify\n try {\n const json = safeStringify(value) ?? '';\n size += json.length * 2;\n } catch {\n size += 1024; // fallback estimate\n }\n\n return size;\n }\n}\n","import { randomUUID } from 'crypto';\nimport type { DedupeStore } from '@comic-vine/client';\n\n// Simple deferred promise helper to avoid non-null assertions\nfunction deferred<T>() {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject } as const;\n}\n\ninterface DedupeJob<T> {\n jobId: string;\n promise: Promise<T | undefined>;\n resolve: (value: T | undefined) => void;\n reject: (reason: unknown) => void;\n createdAt: number;\n completed: boolean;\n result?: T;\n error?: Error;\n}\n\nexport interface InMemoryDedupeStoreOptions {\n jobTimeoutMs?: number;\n cleanupIntervalMs?: number;\n}\n\nexport class InMemoryDedupeStore<T = unknown> implements DedupeStore<T> {\n private jobs = new Map<string, DedupeJob<T>>();\n private readonly jobTimeoutMs: number;\n private cleanupInterval?: NodeJS.Timeout;\n private totalJobsProcessed: number = 0;\n private destroyed: boolean = false;\n\n constructor({\n /** Job timeout in milliseconds. Defaults to 5 minutes. */\n jobTimeoutMs = 300_000,\n /** Cleanup interval in milliseconds. Defaults to 1 minute. */\n cleanupIntervalMs = 60_000,\n }: InMemoryDedupeStoreOptions = {}) {\n this.jobTimeoutMs = jobTimeoutMs;\n\n if (cleanupIntervalMs > 0) {\n this.cleanupInterval = setInterval(() => {\n this.cleanup();\n }, cleanupIntervalMs);\n }\n }\n\n async waitFor(hash: string): Promise<T | undefined> {\n if (this.destroyed) {\n return undefined;\n }\n\n const job = this.jobs.get(hash);\n if (!job) {\n return undefined;\n }\n\n const jobTimedOut =\n this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;\n if (jobTimedOut) {\n this.cleanup();\n return undefined;\n }\n\n // If job is already completed, return the result or throw the error\n if (job.completed) {\n if (job.error) {\n return undefined; // Return undefined for failed jobs instead of throwing\n }\n return job.result ?? undefined;\n }\n\n try {\n return await job.promise;\n } catch {\n // The job promise was rejected, return undefined for failed jobs\n return undefined;\n }\n }\n\n async register(hash: string): Promise<string> {\n // Check if there's already a job for this hash\n const existingJob = this.jobs.get(hash);\n if (existingJob) {\n // Return the existing job ID\n return existingJob.jobId;\n }\n\n // Create a new job\n const jobId = randomUUID();\n const { promise, resolve, reject } = deferred<T | undefined>();\n\n const job: DedupeJob<T> = {\n jobId,\n promise,\n resolve,\n reject,\n createdAt: Date.now(),\n completed: false,\n };\n\n this.jobs.set(hash, job);\n this.totalJobsProcessed++;\n return jobId;\n }\n\n async complete(hash: string, value: T): Promise<void> {\n const job = this.jobs.get(hash);\n if (job && !job.completed) {\n job.completed = true;\n job.result = value;\n job.resolve(value);\n }\n }\n\n async fail(hash: string, error: Error): Promise<void> {\n const job = this.jobs.get(hash);\n if (job && !job.completed) {\n job.completed = true;\n job.error = error;\n job.reject(error);\n }\n }\n\n async isInProgress(hash: string): Promise<boolean> {\n const job = this.jobs.get(hash);\n if (!job) {\n return false;\n }\n\n const isJobExpired =\n this.jobTimeoutMs > 0 && Date.now() - job.createdAt > this.jobTimeoutMs;\n if (isJobExpired) {\n this.cleanup();\n return false;\n }\n\n return !job.completed;\n }\n\n /**\n * Get statistics about current dedupe jobs\n */\n getStats(): {\n activeJobs: number;\n totalJobsProcessed: number;\n expiredJobs: number;\n oldestJobAgeMs: number;\n } {\n const now = Date.now();\n let expiredJobs = 0;\n let oldestJobAgeMs = 0;\n let activeJobs = 0;\n\n for (const [_hash, job] of this.jobs) {\n const ageMs = now - job.createdAt;\n if (this.jobTimeoutMs > 0 && ageMs > this.jobTimeoutMs) {\n expiredJobs++;\n }\n if (ageMs > oldestJobAgeMs) {\n oldestJobAgeMs = ageMs;\n }\n // Only count jobs that are not completed as active\n if (!job.completed) {\n activeJobs++;\n }\n }\n\n return {\n activeJobs,\n totalJobsProcessed: this.totalJobsProcessed,\n expiredJobs,\n oldestJobAgeMs,\n };\n }\n\n /**\n * Clean up expired jobs\n */\n cleanup(): void {\n // Skip cleanup if timeout is disabled\n if (this.jobTimeoutMs <= 0) {\n return;\n }\n\n const now = Date.now();\n const toDelete: Array<string> = [];\n\n for (const [hash, job] of this.jobs) {\n if (now - job.createdAt > this.jobTimeoutMs) {\n if (!job.completed) {\n // Reject the expired job\n job.completed = true;\n job.error = new Error(\n 'Job timeout: Request took too long to complete',\n );\n job.reject(job.error);\n }\n toDelete.push(hash);\n }\n }\n\n for (const hash of toDelete) {\n this.jobs.delete(hash);\n }\n }\n\n /**\n * Clear all jobs\n */\n clear(): void {\n // Reject all pending jobs\n for (const [_hash, job] of this.jobs) {\n if (!job.completed) {\n job.completed = true;\n job.error = new Error('DedupeStore cleared');\n job.reject(job.error);\n }\n }\n this.jobs.clear();\n }\n\n /**\n * Destroy the store and clean up resources\n */\n destroy(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = undefined;\n }\n this.clear();\n this.destroyed = true;\n }\n}\n","import {\n type RateLimitConfig,\n type RateLimitStore,\n DEFAULT_RATE_LIMIT,\n} from '@comic-vine/client';\n\ninterface RateLimitInfo {\n requests: Array<number>;\n limit: number;\n windowMs: number;\n resetTime: number;\n}\n\nexport interface InMemoryRateLimitStoreOptions {\n defaultConfig?: RateLimitConfig;\n resourceConfigs?: Map<string, RateLimitConfig>;\n cleanupIntervalMs?: number;\n}\n\nexport class InMemoryRateLimitStore implements RateLimitStore {\n private limits = new Map<string, RateLimitInfo>();\n private defaultConfig: RateLimitConfig;\n private resourceConfigs = new Map<string, RateLimitConfig>();\n private cleanupInterval?: NodeJS.Timeout;\n private totalRequests: number = 0;\n\n constructor({\n /** Global/default rate-limit config applied when a resource-specific override is not provided. */\n defaultConfig = DEFAULT_RATE_LIMIT,\n /** Optional per-resource overrides. */\n resourceConfigs = new Map(),\n /** Cleanup interval in milliseconds. Defaults to 1 minute. */\n cleanupIntervalMs = 60_000,\n }: InMemoryRateLimitStoreOptions = {}) {\n this.defaultConfig = defaultConfig;\n this.resourceConfigs = resourceConfigs;\n\n if (cleanupIntervalMs > 0) {\n this.cleanupInterval = setInterval(() => {\n this.cleanup();\n }, cleanupIntervalMs);\n }\n }\n\n async canProceed(resource: string): Promise<boolean> {\n const config = this.resourceConfigs.get(resource) || this.defaultConfig;\n const info = this.getOrCreateRateLimitInfo(resource, config);\n\n this.cleanupExpiredRequests(info);\n\n return info.requests.length < info.limit;\n }\n\n async record(resource: string): Promise<void> {\n const config = this.resourceConfigs.get(resource) || this.defaultConfig;\n const info = this.getOrCreateRateLimitInfo(resource, config);\n\n this.cleanupExpiredRequests(info);\n\n const now = Date.now();\n info.requests.push(now);\n this.totalRequests++;\n\n // Update reset time to be one window from now\n info.resetTime = now + config.windowMs;\n }\n\n async getStatus(resource: string): Promise<{\n remaining: number;\n resetTime: Date;\n limit: number;\n }> {\n const config = this.resourceConfigs.get(resource) || this.defaultConfig;\n const info = this.getOrCreateRateLimitInfo(resource, config);\n\n this.cleanupExpiredRequests(info);\n\n return {\n remaining: Math.max(0, info.limit - info.requests.length),\n resetTime: new Date(info.resetTime),\n limit: info.limit,\n };\n }\n\n async reset(resource: string): Promise<void> {\n const info = this.limits.get(resource);\n if (info) {\n // Subtract the requests for this resource from total count\n this.totalRequests = Math.max(\n 0,\n this.totalRequests - info.requests.length,\n );\n }\n this.limits.delete(resource);\n }\n\n async getWaitTime(resource: string): Promise<number> {\n const config = this.resourceConfigs.get(resource) || this.defaultConfig;\n const info = this.getOrCreateRateLimitInfo(resource, config);\n\n this.cleanupExpiredRequests(info);\n\n // Special case: if limit is 0, always return the time until window resets\n if (info.limit === 0) {\n return Math.max(0, info.resetTime - Date.now());\n }\n\n if (info.requests.length < info.limit) {\n return 0;\n }\n\n // Find the oldest request that's still within the window\n const oldestRequest = info.requests[0];\n if (oldestRequest === undefined) {\n return 0;\n }\n const timeUntilOldestExpires = oldestRequest + config.windowMs - Date.now();\n\n return Math.max(0, timeUntilOldestExpires);\n }\n\n /**\n * Set rate limit configuration for a specific resource\n */\n setResourceConfig(resource: string, config: RateLimitConfig): void {\n this.resourceConfigs.set(resource, config);\n // Reset existing limits for this resource to apply new config\n this.limits.delete(resource);\n }\n\n /**\n * Get rate limit configuration for a resource\n */\n getResourceConfig(resource: string): RateLimitConfig {\n return this.resourceConfigs.get(resource) || this.defaultConfig;\n }\n\n /**\n * Get statistics for all resources\n */\n getStats(): {\n totalResources: number;\n activeResources: number;\n rateLimitedResources: number;\n totalRequests: number;\n } {\n let activeResources = 0;\n let rateLimitedResources = 0;\n\n for (const [_resource, info] of this.limits) {\n this.cleanupExpiredRequests(info);\n\n if (info.requests.length > 0) {\n activeResources++;\n if (info.requests.length >= info.limit) {\n rateLimitedResources++;\n }\n }\n }\n\n return {\n totalResources: this.limits.size,\n activeResources,\n rateLimitedResources,\n totalRequests: this.totalRequests,\n };\n }\n\n /**\n * Clear all rate limit data\n */\n clear(): void {\n this.limits.clear();\n this.totalRequests = 0;\n }\n\n /**\n * Clean up expired requests for all resources\n */\n cleanup(): void {\n for (const [_resource, info] of this.limits) {\n this.cleanupExpiredRequests(info);\n }\n }\n\n /**\n * Destroy the store and clean up resources\n */\n destroy(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = undefined;\n }\n this.clear();\n }\n\n private getOrCreateRateLimitInfo(\n resource: string,\n config: RateLimitConfig,\n ): RateLimitInfo {\n let info = this.limits.get(resource);\n if (!info) {\n info = {\n requests: [],\n limit: config.limit,\n windowMs: config.windowMs,\n resetTime: Date.now() + config.windowMs,\n };\n this.limits.set(resource, info);\n }\n return info;\n }\n\n private cleanupExpiredRequests(info: RateLimitInfo): void {\n const now = Date.now();\n const cutoff = now - info.windowMs;\n const initialLength = info.requests.length;\n\n // Remove requests older than the window\n while (info.requests.length > 0 && info.requests[0]! < cutoff) {\n info.requests.shift();\n }\n\n // Update total request count to reflect removed expired requests\n const expiredCount = initialLength - info.requests.length;\n this.totalRequests = Math.max(0, this.totalRequests - expiredCount);\n\n // Update reset time if no requests remain\n if (info.requests.length === 0) {\n info.resetTime = now + info.windowMs;\n }\n }\n}\n","import {\n AdaptiveConfigSchema,\n type AdaptiveRateLimitStore as IAdaptiveRateLimitStore,\n type RequestPriority,\n AdaptiveCapacityCalculator,\n type ActivityMetrics,\n type DynamicCapacityResult,\n} from '@comic-vine/client';\nimport { z } from 'zod';\n\nexport interface AdaptiveRateLimitStoreOptions {\n adaptiveConfig?: Partial<z.input<typeof AdaptiveConfigSchema>>;\n}\n\n/**\n * In-memory rate limiting store with adaptive priority-based capacity allocation\n */\nexport class AdaptiveRateLimitStore implements IAdaptiveRateLimitStore {\n private activityMetrics = new Map<string, ActivityMetrics>();\n private capacityCalculator: AdaptiveCapacityCalculator;\n private lastCapacityUpdate = new Map<string, number>();\n private cachedCapacity = new Map<string, DynamicCapacityResult>();\n\n constructor(options: AdaptiveRateLimitStoreOptions = {}) {\n this.capacityCalculator = new AdaptiveCapacityCalculator(\n options.adaptiveConfig,\n );\n }\n\n async canProceed(\n resource: string,\n priority: RequestPriority = 'background',\n ): Promise<boolean> {\n const metrics = this.getOrCreateActivityMetrics(resource);\n const capacity = this.calculateCurrentCapacity(resource, metrics);\n\n // Check if background requests should be paused\n if (priority === 'background' && capacity.backgroundPaused) {\n return false; // Hard pause for background requests\n }\n\n // Get current usage\n const currentUserRequests = this.getCurrentUsage(\n metrics.recentUserRequests,\n );\n const currentBackgroundRequests = this.getCurrentUsage(\n metrics.recentBackgroundRequests,\n );\n\n if (priority === 'user') {\n return currentUserRequests < capacity.userReserved;\n } else {\n return currentBackgroundRequests < capacity.backgroundMax;\n }\n }\n\n async record(\n resource: string,\n priority: RequestPriority = 'background',\n ): Promise<void> {\n const metrics = this.getOrCreateActivityMetrics(resource);\n const now = Date.now();\n\n if (priority === 'user') {\n metrics.recentUserRequests.push(now);\n this.cleanupOldRequests(metrics.recentUserRequests);\n } else {\n metrics.recentBackgroundRequests.push(now);\n this.cleanupOldRequests(metrics.recentBackgroundRequests);\n }\n\n // Update activity trend\n metrics.userActivityTrend = this.capacityCalculator.calculateActivityTrend(\n metrics.recentUserRequests,\n );\n }\n\n async getStatus(resource: string): Promise<{\n remaining: number;\n resetTime: Date;\n limit: number;\n adaptive?: {\n userReserved: number;\n backgroundMax: number;\n backgroundPaused: boolean;\n recentUserActivity: number;\n reason: string;\n };\n }> {\n const metrics = this.getOrCreateActivityMetrics(resource);\n const capacity = this.calculateCurrentCapacity(resource, metrics);\n const currentUserUsage = this.getCurrentUsage(metrics.recentUserRequests);\n const currentBackgroundUsage = this.getCurrentUsage(\n metrics.recentBackgroundRequests,\n );\n\n return {\n remaining:\n capacity.userReserved -\n currentUserUsage +\n (capacity.backgroundMax - currentBackgroundUsage),\n resetTime: new Date(\n Date.now() + this.capacityCalculator.config.monitoringWindowMs,\n ),\n limit: this.getResourceLimit(resource),\n adaptive: {\n userReserved: capacity.userReserved,\n backgroundMax: capacity.backgroundMax,\n backgroundPaused: capacity.backgroundPaused,\n recentUserActivity: this.capacityCalculator.getRecentActivity(\n metrics.recentUserRequests,\n ),\n reason: capacity.reason,\n },\n };\n }\n\n async reset(resource: string): Promise<void> {\n this.activityMetrics.delete(resource);\n this.cachedCapacity.delete(resource);\n this.lastCapacityUpdate.delete(resource);\n }\n\n async getWaitTime(\n resource: string,\n priority: RequestPriority = 'background',\n ): Promise<number> {\n const canProceed = await this.canProceed(resource, priority);\n if (canProceed) {\n return 0;\n }\n\n const metrics = this.getOrCreateActivityMetrics(resource);\n const capacity = this.calculateCurrentCapacity(resource, metrics);\n\n // If background is paused, wait until next recalculation\n if (priority === 'background' && capacity.backgroundPaused) {\n const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;\n const nextUpdate =\n lastUpdate + this.capacityCalculator.config.recalculationIntervalMs;\n return Math.max(0, nextUpdate - Date.now());\n }\n\n // Otherwise, wait until requests age out of the monitoring window\n const monitoringWindow = this.capacityCalculator.config.monitoringWindowMs;\n const requests =\n priority === 'user'\n ? metrics.recentUserRequests\n : metrics.recentBackgroundRequests;\n\n if (requests.length === 0) {\n return 0;\n }\n\n // Wait until the oldest request falls out of the monitoring window\n const oldestRequest = Math.min(...requests);\n const waitTime = oldestRequest + monitoringWindow - Date.now();\n return Math.max(0, waitTime);\n }\n\n private calculateCurrentCapacity(\n resource: string,\n metrics: ActivityMetrics,\n ): DynamicCapacityResult {\n // Only recalculate based on configured interval to avoid thrashing\n const lastUpdate = this.lastCapacityUpdate.get(resource) || 0;\n const recalcInterval =\n this.capacityCalculator.config.recalculationIntervalMs;\n\n if (Date.now() - lastUpdate < recalcInterval) {\n return (\n this.cachedCapacity.get(resource) || this.getDefaultCapacity(resource)\n );\n }\n\n const totalLimit = this.getResourceLimit(resource);\n const capacity = this.capacityCalculator.calculateDynamicCapacity(\n resource,\n totalLimit,\n metrics,\n );\n\n this.cachedCapacity.set(resource, capacity);\n this.lastCapacityUpdate.set(resource, Date.now());\n\n return capacity;\n }\n\n private getOrCreateActivityMetrics(resource: string): ActivityMetrics {\n if (!this.activityMetrics.has(resource)) {\n this.activityMetrics.set(resource, {\n recentUserRequests: [],\n recentBackgroundRequests: [],\n userActivityTrend: 'none',\n });\n }\n return this.activityMetrics.get(resource)!;\n }\n\n private getCurrentUsage(requests: Array<number>): number {\n const oneHourAgo = Date.now() - 3600000; // 1 hour = 3600000ms\n return requests.filter((timestamp) => timestamp > oneHourAgo).length;\n }\n\n private cleanupOldRequests(requests: Array<number>): void {\n const cutoff =\n Date.now() - this.capacityCalculator.config.monitoringWindowMs;\n while (requests.length > 0 && requests[0]! < cutoff) {\n requests.shift();\n }\n }\n\n private getResourceLimit(_resource: string): number {\n // Default Comic Vine API limits - 200 requests per hour for most resources\n return 200;\n }\n\n private getDefaultCapacity(resource: string): DynamicCapacityResult {\n const totalLimit = this.getResourceLimit(resource);\n return {\n userReserved: Math.floor(totalLimit * 0.3),\n backgroundMax: Math.floor(totalLimit * 0.7),\n backgroundPaused: false,\n reason: 'Default capacity allocation',\n };\n }\n}\n"]}