@sailboat-computer/data-storage
Version:
Shared data storage library for sailboat computer v3
286 lines • 10.6 kB
JavaScript
"use strict";
/**
* Lifecycle manager implementation
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLifecycleManager = exports.LifecycleManagerImpl = void 0;
const types_1 = require("../types");
const errors_1 = require("../utils/errors");
/**
* Lifecycle manager implementation
*/
class LifecycleManagerImpl {
/**
* Create a new lifecycle manager
*
* @param storageManager - Storage manager
* @param downsamplingEngine - Downsampling engine
*/
constructor(storageManager, downsamplingEngine) {
this.storageManager = storageManager;
this.downsamplingEngine = downsamplingEngine;
this.initialized = false;
this.beforeMigrationHandlers = [];
this.afterMigrationHandlers = [];
this.beforeDownsamplingHandlers = [];
this.afterDownsamplingHandlers = [];
}
/**
* Initialize the lifecycle manager
*
* @param config - Lifecycle manager configuration
*/
initialize(config) {
if (this.initialized) {
return;
}
this.config = config;
// Start scheduled cleanup
if (this.config.cleanupInterval > 0) {
this.cleanupInterval = setInterval(() => {
this.runCleanup().catch(error => {
console.error('Error during scheduled cleanup:', error);
});
}, this.config.cleanupInterval);
}
// Start scheduled migration
if (this.config.migrationInterval > 0) {
this.migrationInterval = setInterval(() => {
this.runMigration().catch(error => {
console.error('Error during scheduled migration:', error);
});
}, this.config.migrationInterval);
}
// Initialize downsampling engine if provided
if (this.downsamplingEngine && this.config.downsamplingRules) {
this.downsamplingEngine.initialize(this.config.downsamplingRules);
}
this.initialized = true;
console.log('Lifecycle manager initialized');
}
/**
* Run cleanup for all policies
*/
async runCleanup() {
this.ensureInitialized();
try {
// Get all policies
const policies = this.config.policies;
// Run cleanup for each policy
for (const policy of policies) {
await this.runCleanupForPolicy(policy);
}
}
catch (error) {
console.error('Failed to run cleanup:', error);
throw new errors_1.StorageError(errors_1.StorageErrorCode.CLEANUP_FAILED, 'Failed to run cleanup', { error });
}
}
/**
* Run migration for all policies
*/
async runMigration() {
this.ensureInitialized();
try {
// Get all policies
const policies = this.config.policies;
// Run migration for each policy
for (const policy of policies) {
await this.runMigrationForPolicy(policy);
}
}
catch (error) {
console.error('Failed to run migration:', error);
throw new errors_1.StorageError(errors_1.StorageErrorCode.MIGRATION_FAILED, 'Failed to run migration', { error });
}
}
/**
* Run downsampling for a specific rule
*
* @param ruleId - Downsampling rule ID
*/
async runDownsampling(ruleId) {
this.ensureInitialized();
if (!this.downsamplingEngine) {
throw new errors_1.StorageError(errors_1.StorageErrorCode.SYSTEM_ERROR, 'Downsampling engine not provided', {});
}
try {
// Find rule
const rule = this.config.downsamplingRules.find(r => r.id === ruleId);
if (!rule) {
throw new Error(`Downsampling rule ${ruleId} not found`);
}
// Find policy for rule
const policy = this.config.policies.find(p => p.downsamplingRuleId === ruleId);
if (!policy) {
throw new Error(`No policy found for downsampling rule ${ruleId}`);
}
// Get data to downsample
const data = await this.storageManager.retrieve({
category: policy.category
});
if (data.length === 0) {
console.log(`No data found for downsampling rule ${ruleId}`);
return;
}
// Run downsampling
const downsampledData = await this.downsamplingEngine.downsample(data);
// Update data
for (const item of downsampledData) {
await this.storageManager.update(item);
}
console.log(`Downsampling completed for rule ${ruleId}`);
}
catch (error) {
console.error(`Failed to run downsampling for rule ${ruleId}:`, error);
throw new errors_1.StorageError(errors_1.StorageErrorCode.DOWNSAMPLING_FAILED, `Failed to run downsampling for rule ${ruleId}`, { ruleId, error });
}
}
/**
* Get all lifecycle policies
*
* @returns Lifecycle policies
*/
getPolicies() {
this.ensureInitialized();
return this.config.policies;
}
/**
* Stop the lifecycle manager
*/
stop() {
// Stop scheduled cleanup
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = undefined;
}
// Stop scheduled migration
if (this.migrationInterval) {
clearInterval(this.migrationInterval);
this.migrationInterval = undefined;
}
console.log('Lifecycle manager stopped');
}
/**
* Register a handler to be called before migration
*
* @param handler - Migration handler
*/
onBeforeMigration(handler) {
this.beforeMigrationHandlers.push(handler);
}
/**
* Register a handler to be called after migration
*
* @param handler - Migration handler
*/
onAfterMigration(handler) {
this.afterMigrationHandlers.push(handler);
}
/**
* Register a handler to be called before downsampling
*
* @param handler - Downsampling handler
*/
onBeforeDownsampling(handler) {
this.beforeDownsamplingHandlers.push(handler);
}
/**
* Register a handler to be called after downsampling
*
* @param handler - Downsampling handler
*/
onAfterDownsampling(handler) {
this.afterDownsamplingHandlers.push(handler);
}
/**
* Run cleanup for a specific policy
*
* @param policy - Lifecycle policy
*/
async runCleanupForPolicy(policy) {
try {
// Run cleanup for each tier
if (policy.hotRetentionDays > 0) {
await this.storageManager.cleanup(policy.category, types_1.StorageTier.HOT, policy.hotRetentionDays);
}
if (policy.warmRetentionDays > 0) {
await this.storageManager.cleanup(policy.category, types_1.StorageTier.WARM, policy.warmRetentionDays);
}
if (policy.coldRetentionDays > 0) {
await this.storageManager.cleanup(policy.category, types_1.StorageTier.COLD, policy.coldRetentionDays);
}
console.log(`Cleanup completed for category ${policy.category}`);
}
catch (error) {
console.error(`Failed to run cleanup for category ${policy.category}:`, error);
throw new errors_1.StorageError(errors_1.StorageErrorCode.CLEANUP_FAILED, `Failed to run cleanup for category ${policy.category}`, { category: policy.category, error });
}
}
/**
* Run migration for a specific policy
*
* @param policy - Lifecycle policy
*/
async runMigrationForPolicy(policy) {
try {
// Calculate migration thresholds
const now = new Date();
const hotThreshold = new Date(now.getTime() - policy.migrationThresholdDays * 24 * 60 * 60 * 1000);
// Find data to migrate from hot to warm
const hotData = await this.storageManager.retrieve({
category: policy.category,
timeRange: {
end: hotThreshold.toISOString()
}
}, types_1.StorageTier.HOT);
// Migrate data from hot to warm
for (const item of hotData) {
await this.storageManager.migrate(item.metadata.id, types_1.StorageTier.HOT, types_1.StorageTier.WARM);
}
// Find data to migrate from warm to cold
const warmThreshold = new Date(now.getTime() - policy.warmRetentionDays * 24 * 60 * 60 * 1000);
const warmData = await this.storageManager.retrieve({
category: policy.category,
timeRange: {
end: warmThreshold.toISOString()
}
}, types_1.StorageTier.WARM);
// Migrate data from warm to cold
for (const item of warmData) {
await this.storageManager.migrate(item.metadata.id, types_1.StorageTier.WARM, types_1.StorageTier.COLD);
}
console.log(`Migration completed for category ${policy.category}`);
}
catch (error) {
console.error(`Failed to run migration for category ${policy.category}:`, error);
throw new errors_1.StorageError(errors_1.StorageErrorCode.MIGRATION_FAILED, `Failed to run migration for category ${policy.category}`, { category: policy.category, error });
}
}
/**
* Ensure lifecycle manager is initialized
*
* @throws StorageError if not initialized
*/
ensureInitialized() {
if (!this.initialized || !this.config) {
throw new errors_1.StorageError(errors_1.StorageErrorCode.SYSTEM_ERROR, 'Lifecycle manager not initialized', {});
}
}
}
exports.LifecycleManagerImpl = LifecycleManagerImpl;
/**
* Create a new lifecycle manager
*
* @param storageManager - Storage manager
* @param config - Lifecycle manager configuration
* @param downsamplingEngine - Downsampling engine (optional)
* @returns Lifecycle manager
*/
function createLifecycleManager(storageManager, config, downsamplingEngine) {
const manager = new LifecycleManagerImpl(storageManager, downsamplingEngine);
manager.initialize(config);
return manager;
}
exports.createLifecycleManager = createLifecycleManager;
//# sourceMappingURL=manager.js.map