UNPKG

cachly

Version:

Type-safe, production-ready in-memory cache system for Node.js and TypeScript with advanced features.

115 lines (96 loc) 3.33 kB
import { PartitioningConfig, PartitionInfo } from '../types'; export class PartitioningUtil { private config: PartitioningConfig; private partitions: Map<number, PartitionInfo> = new Map(); constructor(config: PartitioningConfig) { this.config = config; this.initializePartitions(); } private initializePartitions(): void { for (let i = 0; i < this.config.partitions; i++) { this.partitions.set(i, { id: i, keyCount: 0, memoryUsage: 0, hitRate: 0, }); } } getPartition(key: string): number { if (!this.config.enabled) return 0; let partitionKey: string; if (this.config.partitionKey) { partitionKey = this.config.partitionKey(key); } else { partitionKey = key; } switch (this.config.strategy) { case 'hash': return this.hashPartition(partitionKey); case 'range': return this.rangePartition(partitionKey); case 'custom': return this.customPartition(partitionKey); default: return this.hashPartition(partitionKey); } } private hashPartition(key: string): number { let hash = 0; for (let i = 0; i < key.length; i++) { const char = key.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash) % this.config.partitions; } private rangePartition(key: string): number { const firstChar = key.charAt(0).toLowerCase(); const charCode = firstChar.charCodeAt(0); return charCode % this.config.partitions; } private customPartition(key: string): number { // Custom partitioning logic - can be extended return this.hashPartition(key); } updatePartitionStats(partitionId: number, keyCount: number, memoryUsage: number, hitRate: number): void { const partition = this.partitions.get(partitionId); if (partition) { partition.keyCount = keyCount; partition.memoryUsage = memoryUsage; partition.hitRate = hitRate; } } getPartitionInfo(partitionId: number): PartitionInfo | undefined { return this.partitions.get(partitionId); } getAllPartitions(): PartitionInfo[] { return Array.from(this.partitions.values()); } getPartitionDistribution(): Record<number, number> { const distribution: Record<number, number> = {}; for (const partition of this.partitions.values()) { distribution[partition.id] = partition.keyCount; } return distribution; } getBalancedPartition(): number { let minKeys = Infinity; let selectedPartition = 0; for (const partition of this.partitions.values()) { if (partition.keyCount < minKeys) { minKeys = partition.keyCount; selectedPartition = partition.id; } } return selectedPartition; } isBalanced(): boolean { const keyCounts = Array.from(this.partitions.values()).map(p => p.keyCount); const avg = keyCounts.reduce((sum, count) => sum + count, 0) / keyCounts.length; const variance = keyCounts.reduce((sum, count) => sum + Math.pow(count - avg, 2), 0) / keyCounts.length; const standardDeviation = Math.sqrt(variance); // Consider balanced if standard deviation is less than 20% of average return standardDeviation < avg * 0.2; } }