cs-element
Version:
Advanced reactive data management library with state machines, blueprints, persistence, compression, networking, and multithreading support
851 lines (845 loc) • 34.8 kB
JavaScript
'use strict';
var pako = require('pako');
var lz4 = require('lz4js');
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var pako__namespace = /*#__PURE__*/_interopNamespaceDefault(pako);
var lz4__namespace = /*#__PURE__*/_interopNamespaceDefault(lz4);
// Типы сжатия
var CompressionAlgorithm;
(function (CompressionAlgorithm) {
CompressionAlgorithm["GZIP"] = "gzip";
CompressionAlgorithm["DEFLATE"] = "deflate";
CompressionAlgorithm["BROTLI"] = "brotli";
CompressionAlgorithm["LZ4"] = "lz4";
CompressionAlgorithm["ZSTD"] = "zstd";
CompressionAlgorithm["SNAPPY"] = "snappy";
})(CompressionAlgorithm || (CompressionAlgorithm = {}));
var CompressionLevel;
(function (CompressionLevel) {
CompressionLevel[CompressionLevel["FASTEST"] = 1] = "FASTEST";
CompressionLevel[CompressionLevel["FAST"] = 3] = "FAST";
CompressionLevel[CompressionLevel["BALANCED"] = 6] = "BALANCED";
CompressionLevel[CompressionLevel["BEST"] = 9] = "BEST";
})(CompressionLevel || (CompressionLevel = {}));
var CompressionMode;
(function (CompressionMode) {
CompressionMode["AUTOMATIC"] = "automatic";
CompressionMode["MANUAL"] = "manual";
CompressionMode["THRESHOLD_BASED"] = "threshold_based";
CompressionMode["SELECTIVE"] = "selective";
})(CompressionMode || (CompressionMode = {}));
var DataType;
(function (DataType) {
DataType["JSON"] = "json";
DataType["TEXT"] = "text";
DataType["BINARY"] = "binary";
DataType["IMAGE"] = "image";
DataType["AUDIO"] = "audio";
DataType["VIDEO"] = "video";
})(DataType || (DataType = {}));
class CompressionPlugin {
constructor(config = {}) {
this.name = 'CompressionPlugin';
this.version = '1.0.0';
this.description = 'Плагин для сжатия данных и оптимизации памяти';
this.rules = new Map();
this.profiles = new Map();
this.jobs = new Map();
this.cache = new Map();
this.compressedElements = new Map();
this.config = {
enabled: true,
priority: 150,
defaultAlgorithm: CompressionAlgorithm.GZIP,
defaultLevel: CompressionLevel.BALANCED,
mode: CompressionMode.THRESHOLD_BASED,
autoCompress: true,
compressionThreshold: 1024, // 1KB
maxCompressionJobs: 5,
enableCaching: true,
cacheSize: 50 * 1024 * 1024, // 50MB
cacheTTL: 3600000, // 1 час
enableBenchmarking: false,
validateChecksums: true,
enableStatistics: true,
blacklistedDataTypes: [],
whitelistedDataTypes: [],
...config
};
this.stats = {
totalCompressions: 0,
totalDecompressions: 0,
totalOriginalSize: 0,
totalCompressedSize: 0,
averageCompressionRatio: 0,
averageCompressionTime: 0,
averageDecompressionTime: 0,
compressionsByAlgorithm: {},
compressionsByLevel: {},
cacheHits: 0,
cacheMisses: 0,
cacheHitRatio: 0,
activeJobs: 0,
failedCompressions: 0,
savedSpace: 0,
bestCompressionRatio: 0,
worstCompressionRatio: 1
};
// Инициализация счетчиков
Object.values(CompressionAlgorithm).forEach(algorithm => {
this.stats.compressionsByAlgorithm[algorithm] = 0;
});
Object.values(CompressionLevel).forEach(level => {
this.stats.compressionsByLevel[level] = 0;
});
this.initializeDefaultProfiles();
this.initializeDefaultRules();
}
install(_CSElementClass) {
// Регистрация плагина в системе CSElement
// В реальной реализации здесь была бы интеграция с жизненным циклом элементов
console.log(`${this.name} установлен для CSElement`);
}
async initialize() {
console.log(`Инициализация ${this.name} v${this.version}`);
// Очистка кэша по расписанию
if (this.config.enableCaching) {
setInterval(() => {
this.cleanupCache();
}, 60000); // каждую минуту
}
// Обновление статистики
if (this.config.enableStatistics) {
setInterval(() => {
this.updateStats();
}, 30000); // каждые 30 секунд
}
}
async destroy() {
// Завершение активных задач
for (const job of this.jobs.values()) {
if (job.status === 'processing') {
job.status = 'failed';
job.error = 'Plugin shutdown';
job.endTime = new Date();
}
}
this.cache.clear();
console.log(`${this.name} деинициализирован`);
}
getConfig() {
return { ...this.config };
}
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
// Lifecycle hooks
async afterCreate(element, _context) {
if (this.config.autoCompress && this.shouldCompress(element)) {
await this.compressElement(element);
}
return { success: true };
}
async afterUpdate(element, _context) {
if (this.config.autoCompress && this.shouldCompress(element)) {
await this.compressElement(element);
}
return { success: true };
}
async beforeRead(element, _context) {
if (this.isElementCompressed(element)) {
await this.decompressElement(element);
}
return { success: true };
}
// Основные методы сжатия
async compressData(data, options = {}) {
const startTime = Date.now();
const inputBuffer = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf8');
const originalSize = inputBuffer.length;
const compressionOptions = {
algorithm: this.config.defaultAlgorithm,
level: this.config.defaultLevel,
validateChecksum: this.config.validateChecksums,
...options
};
// Проверка кэша
const cacheKey = this.generateCacheKey(inputBuffer, compressionOptions);
if (this.config.enableCaching) {
const cached = this.getCachedCompression(cacheKey);
if (cached) {
this.stats.cacheHits++;
return this.createResultFromCache(cached, originalSize, startTime);
}
this.stats.cacheMisses++;
}
try {
// Выполнение сжатия
const compressedData = await this.performCompression(inputBuffer, compressionOptions);
const compressedSize = compressedData.length;
const compressionRatio = compressedSize / originalSize;
const duration = Date.now() - startTime;
// Вычисление контрольной суммы
const checksum = this.calculateChecksum(compressedData);
const result = {
originalSize,
compressedSize,
compressionRatio,
algorithm: compressionOptions.algorithm,
level: compressionOptions.level,
duration,
checksum,
metadata: {
inputType: Buffer.isBuffer(data) ? 'buffer' : 'string',
timestamp: new Date().toISOString()
}
};
// Сохранение в кэш
if (this.config.enableCaching) {
this.cacheCompression(cacheKey, compressedData, compressionOptions, checksum);
}
// Обновление статистики
this.updateCompressionStats(result);
return result;
}
catch (error) {
this.stats.failedCompressions++;
throw new Error(`Ошибка сжатия: ${error instanceof Error ? error.message : String(error)}`);
}
}
async decompressData(compressedData, algorithm, expectedChecksum) {
const startTime = Date.now();
try {
// Валидация контрольной суммы
if (expectedChecksum && this.config.validateChecksums) {
const actualChecksum = this.calculateChecksum(compressedData);
if (actualChecksum !== expectedChecksum) {
throw new Error('Нарушена целостность сжатых данных');
}
}
// Выполнение декомпрессии
const decompressedData = await this.performDecompression(compressedData, algorithm);
const duration = Date.now() - startTime;
// Обновление статистики
this.stats.totalDecompressions++;
this.stats.averageDecompressionTime =
(this.stats.averageDecompressionTime + duration) / 2;
return decompressedData;
}
catch (error) {
throw new Error(`Ошибка декомпрессии: ${error instanceof Error ? error.message : String(error)}`);
}
}
async compressElement(element) {
if (!this.shouldCompress(element)) {
return null;
}
const jobId = this.generateId();
const serializedData = this.serializeElementForCompression(element);
const dataBuffer = Buffer.from(serializedData, 'utf8');
const job = {
id: jobId,
elementId: element.id,
status: 'pending',
algorithm: this.config.defaultAlgorithm,
level: this.config.defaultLevel,
startTime: new Date(),
originalSize: dataBuffer.length
};
this.jobs.set(jobId, job);
this.stats.activeJobs++;
try {
job.status = 'processing';
// Выбор алгоритма и уровня сжатия
const rule = this.findMatchingRule(element);
const algorithm = rule?.algorithm || this.config.defaultAlgorithm;
const level = rule?.level || this.config.defaultLevel;
const options = {
algorithm,
level,
validateChecksum: this.config.validateChecksums,
...rule?.options
};
// Сжатие данных
const result = await this.compressData(dataBuffer, options);
// Сохранение результата в элементе
element.setData('_compressed', true);
element.setData('_compressionResult', result);
element.setData('_originalData', serializedData);
job.status = 'completed';
job.endTime = new Date();
job.compressedSize = result.compressedSize;
job.result = result;
this.compressedElements.set(element.id, result);
console.log(`Элемент ${element.id} сжат: ${result.originalSize} -> ${result.compressedSize} байт (${(result.compressionRatio * 100).toFixed(1)}%)`);
return result;
}
catch (error) {
job.status = 'failed';
job.error = error instanceof Error ? error.message : String(error);
job.endTime = new Date();
console.error(`Ошибка сжатия элемента ${element.id}:`, error);
return null;
}
finally {
this.stats.activeJobs--;
// Удаление задачи через 5 минут
setTimeout(() => {
this.jobs.delete(jobId);
}, 300000);
}
}
async decompressElement(element) {
if (!this.isElementCompressed(element)) {
return true;
}
try {
const compressionResult = element.getData('_compressionResult');
const originalData = element.getData('_originalData');
if (!compressionResult || !originalData) {
console.error(`Отсутствуют данные для декомпрессии элемента ${element.id}`);
return false;
}
// Восстановление оригинальных данных
const parsedData = JSON.parse(originalData);
// Восстановление данных элемента
Object.keys(parsedData).forEach(key => {
if (!key.startsWith('_compression')) {
element.setData(key, parsedData[key]);
}
});
// Удаление данных сжатия
element.setData('_compressed', false);
element.setData('_compressionResult', undefined);
element.setData('_originalData', undefined);
this.compressedElements.delete(element.id);
console.log(`Элемент ${element.id} декомпрессирован`);
return true;
}
catch (error) {
console.error(`Ошибка декомпрессии элемента ${element.id}:`, error);
return false;
}
}
// Управление профилями
createProfile(profileData) {
const profile = {
id: this.generateId(),
...profileData
};
this.profiles.set(profile.id, profile);
return profile;
}
getProfile(id) {
return this.profiles.get(id);
}
updateProfile(id, updates) {
const profile = this.profiles.get(id);
if (!profile)
return false;
Object.assign(profile, updates);
return true;
}
deleteProfile(id) {
return this.profiles.delete(id);
}
// Управление правилами
addRule(ruleData) {
const rule = {
id: this.generateId(),
createdAt: new Date(),
updatedAt: new Date(),
...ruleData
};
this.rules.set(rule.id, rule);
return rule;
}
getRule(id) {
return this.rules.get(id);
}
updateRule(id, updates) {
const rule = this.rules.get(id);
if (!rule)
return false;
Object.assign(rule, { ...updates, updatedAt: new Date() });
return true;
}
deleteRule(id) {
return this.rules.delete(id);
}
// Бенчмаркинг
async runBenchmark(data, algorithms = Object.values(CompressionAlgorithm), levels = Object.values(CompressionLevel)) {
if (!this.config.enableBenchmarking) {
throw new Error('Бенчмаркинг отключен');
}
const results = [];
const dataType = this.detectDataType(data);
for (const algorithm of algorithms) {
for (const level of levels) {
try {
const compressionStart = Date.now();
const compressionResult = await this.compressData(data, { algorithm, level });
const compressionTime = Date.now() - compressionStart;
const decompressionStart = Date.now();
await this.decompressData(Buffer.from('compressed_data'), // заглушка
algorithm);
const decompressionTime = Date.now() - decompressionStart;
const result = {
dataSize: data.length,
dataType,
algorithm,
level,
compressionRatio: compressionResult.compressionRatio,
compressionTime,
decompressionTime,
memoryUsage: process.memoryUsage().heapUsed,
timestamp: new Date()
};
results.push(result);
}
catch (error) {
console.error(`Ошибка бенчмарка ${algorithm}/${level}:`, error);
}
}
}
return results.sort((a, b) => a.compressionRatio - b.compressionRatio);
}
// Анализ и оптимизация
async analyzeBestAlgorithm(data) {
const benchmarkResults = await this.runBenchmark(data);
if (benchmarkResults.length === 0) {
return this.config.defaultAlgorithm;
}
// Выбор лучшего алгоритма по соотношению сжатия и скорости
const scored = benchmarkResults.map(result => ({
algorithm: result.algorithm,
score: (1 - result.compressionRatio) * 0.7 + (1 / result.compressionTime) * 0.3
}));
scored.sort((a, b) => b.score - a.score);
return scored[0].algorithm;
}
getCompressionRecommendations(element) {
const dataSize = this.serializeElementForCompression(element).length;
const dataType = this.detectElementDataType(element);
// Рекомендации на основе типа и размера данных
if (dataSize < 1024) {
return {
algorithm: CompressionAlgorithm.LZ4,
level: CompressionLevel.FAST,
expectedRatio: 0.8,
reason: 'Малый размер данных - приоритет скорости'
};
}
if (dataType === DataType.TEXT || dataType === DataType.JSON) {
return {
algorithm: CompressionAlgorithm.BROTLI,
level: CompressionLevel.BALANCED,
expectedRatio: 0.4,
reason: 'Текстовые данные хорошо сжимаются Brotli'
};
}
return {
algorithm: this.config.defaultAlgorithm,
level: this.config.defaultLevel,
expectedRatio: 0.6,
reason: 'Стандартные настройки'
};
}
// Утилиты
/**
* Сериализация элемента для сжатия с использованием встроенной сериализации
*/
serializeElementForCompression(element) {
// Используем встроенную сериализацию CSElement
const serialized = element.serialize({
includeChildren: true,
includeData: true,
includeMetadata: true
});
return JSON.stringify(serialized);
}
shouldCompress(element) {
if (!this.config.autoCompress)
return false;
const serializedData = this.serializeElementForCompression(element);
const dataSize = Buffer.byteLength(serializedData, 'utf8');
// Проверка минимального размера
if (dataSize < this.config.compressionThreshold) {
return false;
}
// Проверка лимита задач
if (this.stats.activeJobs >= this.config.maxCompressionJobs) {
return false;
}
// Проверка типов данных
const dataType = this.detectElementDataType(element);
if (this.config.blacklistedDataTypes.includes(dataType)) {
return false;
}
if (this.config.whitelistedDataTypes.length > 0 &&
!this.config.whitelistedDataTypes.includes(dataType)) {
return false;
}
return true;
}
isElementCompressed(element) {
return element.getData('_compressed') === true;
}
findMatchingRule(element) {
const rules = Array.from(this.rules.values())
.filter(rule => rule.enabled)
.sort((a, b) => b.priority - a.priority);
for (const rule of rules) {
if (this.evaluateRuleConditions(rule, element)) {
return rule;
}
}
return undefined;
}
evaluateRuleConditions(rule, element) {
return rule.conditions.every(condition => {
switch (condition.type) {
case 'size':
const size = this.serializeElementForCompression(element).length;
return this.evaluateCondition(size, condition.operator, condition.value);
case 'elementType':
const elementType = element.constructor.name;
return this.evaluateCondition(elementType, condition.operator, condition.value);
case 'dataType':
const dataType = this.detectElementDataType(element);
return this.evaluateCondition(dataType, condition.operator, condition.value);
default:
return true;
}
});
}
evaluateCondition(actual, operator, expected) {
switch (operator) {
case 'equals': return actual === expected;
case 'greater': return actual > expected;
case 'less': return actual < expected;
case 'contains': return String(actual).includes(String(expected));
case 'matches': return new RegExp(expected).test(String(actual));
default: return true;
}
}
detectElementDataType(element) {
const serialized = this.serializeElementForCompression(element);
// Простая эвристика определения типа данных
if (serialized.includes('"image"') || serialized.includes('data:image/')) {
return DataType.IMAGE;
}
if (serialized.includes('"audio"') || serialized.includes('data:audio/')) {
return DataType.AUDIO;
}
if (serialized.includes('"video"') || serialized.includes('data:video/')) {
return DataType.VIDEO;
}
try {
JSON.parse(serialized);
return DataType.JSON;
}
catch {
return DataType.TEXT;
}
}
detectDataType(data) {
// Проверка магических байтов для определения типа
const header = data.slice(0, 16);
// JPEG
if (header[0] === 0xFF && header[1] === 0xD8)
return DataType.IMAGE;
// PNG
if (header.slice(0, 8).equals(Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])))
return DataType.IMAGE;
// PDF
if (header.slice(0, 4).equals(Buffer.from('%PDF')))
return DataType.BINARY;
// Проверка на текст
const text = data.toString('utf8', 0, Math.min(1024, data.length));
try {
JSON.parse(text);
return DataType.JSON;
}
catch {
// Проверка на читаемый текст
const printableChars = text.replace(/[^\x20-\x7E]/g, '').length;
const ratio = printableChars / text.length;
return ratio > 0.8 ? DataType.TEXT : DataType.BINARY;
}
}
async performCompression(data, options) {
try {
switch (options.algorithm) {
case CompressionAlgorithm.GZIP: {
const level = Math.max(0, Math.min(9, options.level));
const compressed = pako__namespace.gzip(data, { level });
return Buffer.from(compressed);
}
case CompressionAlgorithm.DEFLATE: {
const level = Math.max(0, Math.min(9, options.level));
const compressed = pako__namespace.deflate(data, { level });
return Buffer.from(compressed);
}
case CompressionAlgorithm.LZ4: {
const compressed = lz4__namespace.compress(data);
return Buffer.from(compressed);
}
case CompressionAlgorithm.BROTLI:
// Brotli требует дополнительной настройки, пока используем gzip как fallback
console.warn('Brotli сжатие пока не поддерживается, используется GZIP');
const gzipLevel = Math.max(0, Math.min(9, options.level));
const gzipCompressed = pako__namespace.gzip(data, { level: gzipLevel });
return Buffer.from(gzipCompressed);
default:
throw new Error(`Неподдерживаемый алгоритм сжатия: ${options.algorithm}`);
}
}
catch (error) {
console.error('Ошибка сжатия данных:', error);
// В случае ошибки возвращаем исходные данные
return data;
}
}
async performDecompression(data, algorithm) {
try {
switch (algorithm) {
case CompressionAlgorithm.GZIP: {
const decompressed = pako__namespace.ungzip(data);
return Buffer.from(decompressed);
}
case CompressionAlgorithm.DEFLATE: {
const decompressed = pako__namespace.inflate(data);
return Buffer.from(decompressed);
}
case CompressionAlgorithm.LZ4: {
const decompressed = lz4__namespace.decompress(data);
return Buffer.from(decompressed);
}
case CompressionAlgorithm.BROTLI:
// Brotli декомпрессия пока не поддерживается, используем gzip как fallback
console.warn('Brotli декомпрессия пока не поддерживается, используется GZIP');
const gzipDecompressed = pako__namespace.ungzip(data);
return Buffer.from(gzipDecompressed);
default:
throw new Error(`Неподдерживаемый алгоритм декомпрессии: ${algorithm}`);
}
}
catch (error) {
console.error('Ошибка декомпрессии данных:', error);
// В случае ошибки возвращаем исходные данные
return data;
}
}
generateCacheKey(data, options) {
const dataHash = this.calculateChecksum(data);
const optionsHash = this.calculateChecksum(Buffer.from(JSON.stringify(options)));
return `${dataHash}-${optionsHash}`;
}
getCachedCompression(key) {
const cached = this.cache.get(key);
if (!cached)
return undefined;
// Проверка TTL
if (Date.now() - cached.createdAt.getTime() > this.config.cacheTTL) {
this.cache.delete(key);
return undefined;
}
cached.lastAccessed = new Date();
cached.accessCount++;
return cached;
}
cacheCompression(key, data, options, checksum) {
// Проверка лимита размера кэша
if (this.getCurrentCacheSize() + data.length > this.config.cacheSize) {
this.evictLeastRecentlyUsed();
}
const cacheEntry = {
key,
data,
algorithm: options.algorithm,
level: options.level,
checksum,
createdAt: new Date(),
lastAccessed: new Date(),
accessCount: 1,
size: data.length
};
this.cache.set(key, cacheEntry);
}
createResultFromCache(cached, originalSize, startTime) {
return {
originalSize,
compressedSize: cached.size,
compressionRatio: cached.size / originalSize,
algorithm: cached.algorithm,
level: cached.level,
duration: Date.now() - startTime,
checksum: cached.checksum,
metadata: {
fromCache: true,
cacheHit: true
}
};
}
cleanupCache() {
const now = Date.now();
const toDelete = [];
for (const [key, entry] of this.cache.entries()) {
if (now - entry.createdAt.getTime() > this.config.cacheTTL) {
toDelete.push(key);
}
}
toDelete.forEach(key => this.cache.delete(key));
if (toDelete.length > 0) {
console.log(`Удалено ${toDelete.length} устаревших записей из кэша сжатия`);
}
}
evictLeastRecentlyUsed() {
const entries = Array.from(this.cache.entries());
entries.sort((a, b) => a[1].lastAccessed.getTime() - b[1].lastAccessed.getTime());
// Удаляем 25% наименее используемых записей
const toEvict = Math.ceil(entries.length * 0.25);
for (let i = 0; i < toEvict; i++) {
this.cache.delete(entries[i][0]);
}
}
getCurrentCacheSize() {
return Array.from(this.cache.values()).reduce((total, entry) => total + entry.size, 0);
}
updateCompressionStats(result) {
this.stats.totalCompressions++;
this.stats.totalOriginalSize += result.originalSize;
this.stats.totalCompressedSize += result.compressedSize;
this.stats.savedSpace += (result.originalSize - result.compressedSize);
this.stats.averageCompressionRatio = this.stats.totalCompressedSize / this.stats.totalOriginalSize;
this.stats.averageCompressionTime = (this.stats.averageCompressionTime + result.duration) / 2;
this.stats.compressionsByAlgorithm[result.algorithm]++;
this.stats.compressionsByLevel[result.level]++;
this.stats.lastCompressionTime = new Date();
if (result.compressionRatio > this.stats.bestCompressionRatio) {
this.stats.bestCompressionRatio = result.compressionRatio;
}
if (result.compressionRatio < this.stats.worstCompressionRatio) {
this.stats.worstCompressionRatio = result.compressionRatio;
}
}
updateStats() {
if (this.stats.cacheHits + this.stats.cacheMisses > 0) {
this.stats.cacheHitRatio = this.stats.cacheHits / (this.stats.cacheHits + this.stats.cacheMisses);
}
}
initializeDefaultProfiles() {
// Профиль для текстовых данных
this.createProfile({
name: 'Text Optimized',
description: 'Оптимизирован для текстовых данных',
dataTypes: [DataType.TEXT, DataType.JSON],
algorithm: CompressionAlgorithm.BROTLI,
level: CompressionLevel.BALANCED,
options: {
algorithm: CompressionAlgorithm.BROTLI,
level: CompressionLevel.BALANCED,
validateChecksum: true
},
isDefault: true
});
// Профиль для бинарных данных
this.createProfile({
name: 'Binary Optimized',
description: 'Оптимизирован для бинарных данных',
dataTypes: [DataType.BINARY, DataType.IMAGE],
algorithm: CompressionAlgorithm.LZ4,
level: CompressionLevel.FAST,
options: {
algorithm: CompressionAlgorithm.LZ4,
level: CompressionLevel.FAST,
validateChecksum: true
},
isDefault: false
});
}
initializeDefaultRules() {
// Правило для больших данных
this.addRule({
name: 'Large Data',
description: 'Максимальное сжатие для больших данных',
enabled: true,
priority: 100,
conditions: [{
type: 'size',
operator: 'greater',
value: 1024 * 1024 // 1MB
}],
algorithm: CompressionAlgorithm.BROTLI,
level: CompressionLevel.BEST
});
// Правило для быстрого сжатия
this.addRule({
name: 'Fast Compression',
description: 'Быстрое сжатие для небольших данных',
enabled: true,
priority: 50,
conditions: [{
type: 'size',
operator: 'less',
value: 10240 // 10KB
}],
algorithm: CompressionAlgorithm.LZ4,
level: CompressionLevel.FASTEST
});
}
calculateChecksum(data) {
// Простая контрольная сумма
let hash = 0;
for (let i = 0; i < data.length; i++) {
hash = ((hash << 5) - hash) + data[i];
hash = hash & hash;
}
return hash.toString(16);
}
generateId() {
return Date.now().toString(36) + Math.random().toString(36).substr(2);
}
// Публичные методы для получения данных
getStats() {
return { ...this.stats };
}
getAllProfiles() {
return Array.from(this.profiles.values());
}
getAllRules() {
return Array.from(this.rules.values());
}
getActiveJobs() {
return Array.from(this.jobs.values()).filter(job => job.status === 'processing');
}
getCompressedElements() {
return new Map(this.compressedElements);
}
getCacheInfo() {
return {
size: this.cache.size,
entries: this.cache.size,
hitRatio: this.stats.cacheHitRatio,
totalSize: this.getCurrentCacheSize()
};
}
}
exports.CompressionPlugin = CompressionPlugin;
//# sourceMappingURL=compression.js.map