114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import { StorageService } from './StorageService';
|
|
import { MinioStorageService } from './MinioStorageService';
|
|
|
|
export class StorageFactory {
|
|
private static instance: StorageService | null = null;
|
|
private static initializationPromise: Promise<StorageService> | null = null;
|
|
|
|
static async getInstance(): Promise<StorageService> {
|
|
if (this.instance) {
|
|
return this.instance;
|
|
}
|
|
|
|
if (this.initializationPromise) {
|
|
return await this.initializationPromise;
|
|
}
|
|
|
|
this.initializationPromise = this.createStorageServiceWithRetry();
|
|
|
|
try {
|
|
this.instance = await this.initializationPromise;
|
|
return this.instance;
|
|
} catch (error) {
|
|
this.initializationPromise = null;
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
static getInstanceSync(): StorageService {
|
|
if (!this.instance) {
|
|
try {
|
|
this.instance = this.createStorageService();
|
|
} catch (error) {
|
|
throw new Error('Storage service unavailable. Please check MinIO configuration.');
|
|
}
|
|
}
|
|
return this.instance;
|
|
}
|
|
|
|
private static async createStorageServiceWithRetry(): Promise<StorageService> {
|
|
const maxRetries = 3;
|
|
const baseDelay = 1000; // 1 second
|
|
|
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
try {
|
|
const service = this.createStorageService();
|
|
|
|
await service.bucketExists();
|
|
|
|
return service;
|
|
} catch (error) {
|
|
if (attempt === maxRetries) {
|
|
throw new Error(
|
|
`Failed to initialize storage service after ${maxRetries} attempts. ` +
|
|
`Last error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
);
|
|
}
|
|
|
|
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
await this.sleep(delay);
|
|
}
|
|
}
|
|
|
|
throw new Error('Unexpected error in storage service creation');
|
|
}
|
|
|
|
private static sleep(ms: number): Promise<void> {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
private static createStorageService(): StorageService {
|
|
const storageType = process.env['STORAGE_TYPE'] || 'minio';
|
|
|
|
try {
|
|
switch (storageType.toLowerCase()) {
|
|
case 'minio': {
|
|
const endpoint = process.env['MINIO_ENDPOINT'];
|
|
const accessKey = process.env['MINIO_ACCESS_KEY'];
|
|
const secretKey = process.env['MINIO_SECRET_KEY'];
|
|
const useSSL = process.env['MINIO_USE_SSL'] === 'true';
|
|
const bucketName = process.env['MINIO_BUCKET_NAME'] || 'banatie';
|
|
const publicUrl = process.env['MINIO_PUBLIC_URL'];
|
|
|
|
console.log(`[StorageFactory] Creating MinIO client with endpoint: ${endpoint}`);
|
|
|
|
if (!endpoint || !accessKey || !secretKey) {
|
|
throw new Error(
|
|
'MinIO configuration missing. Required: MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY',
|
|
);
|
|
}
|
|
|
|
return new MinioStorageService(
|
|
endpoint,
|
|
accessKey,
|
|
secretKey,
|
|
useSSL,
|
|
bucketName,
|
|
publicUrl,
|
|
);
|
|
}
|
|
|
|
default:
|
|
throw new Error(`Unsupported storage type: ${storageType}`);
|
|
}
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
static resetInstance(): void {
|
|
this.instance = null;
|
|
this.initializationPromise = null;
|
|
}
|
|
}
|