// // Copyright 2026 The InfiniFlow Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package storage import ( "fmt" "ragflow/internal/common" "ragflow/internal/server" "sync" ) var ( globalFactory *StorageFactory once sync.Once ) // StorageFactory creates storage instances based on configuration type StorageFactory struct { storageType StorageType storage Storage config *server.StorageConfig mu sync.RWMutex } // GetStorageFactory returns the singleton storage factory instance func GetStorageFactory() *StorageFactory { once.Do(func() { globalFactory = &StorageFactory{} }) return globalFactory } // InitStorageFactory initializes the storage factory with configuration func InitStorageFactory() error { factory := GetStorageFactory() globalConfig := server.GetConfig() factory.config = &globalConfig.StorageEngine // Initialize storage based on type if err := factory.initStorage(); err != nil { return err } common.Info(fmt.Sprintf("Storage initialized: %s", factory.config.Type)) return nil } // initStorage initializes the specific storage implementation func (f *StorageFactory) initStorage() error { switch f.config.Type { case "minio": return f.initMinio(f.config.Minio) case "s3": return f.initS3(f.config.S3) case "oss": return f.initOSS(f.config.OSS) default: return fmt.Errorf("unsupported storage type: %s", f.config.Type) } } func (f *StorageFactory) initMinio(minioConfig *server.MinioConfig) error { storage, err := NewMinioStorage(minioConfig) if err != nil { return fmt.Errorf("failed to create MinIO storage: %w", err) } f.mu.Lock() defer f.mu.Unlock() f.storageType = StorageMinio f.storage = storage f.config.Minio = minioConfig return nil } func (f *StorageFactory) initS3(s3Config *server.S3Config) error { storage, err := NewS3Storage(s3Config) if err != nil { return fmt.Errorf("failed to create S3 storage: %w", err) } f.mu.Lock() defer f.mu.Unlock() f.storageType = StorageAWSS3 f.storage = storage f.config.S3 = s3Config return nil } func (f *StorageFactory) initOSS(ossConfig *server.OSSConfig) error { storage, err := NewOSSStorage(ossConfig) if err != nil { return fmt.Errorf("failed to create OSS storage: %w", err) } f.mu.Lock() defer f.mu.Unlock() f.storageType = StorageOSS f.storage = storage f.config.OSS = ossConfig return nil } // GetStorage returns the current storage instance func (f *StorageFactory) GetStorage() Storage { f.mu.RLock() defer f.mu.RUnlock() return f.storage } // GetStorageType returns the current storage type func (f *StorageFactory) GetStorageType() StorageType { f.mu.RLock() defer f.mu.RUnlock() return f.storageType } // Create creates a new storage instance based on the storage type // This is the factory method equivalent to Python's StorageFactory.create() func (f *StorageFactory) Create(storageType StorageType) (Storage, error) { var storage Storage var err error switch storageType { case StorageMinio: if f.config.Minio != nil { storage, err = NewMinioStorage(f.config.Minio) } else { return nil, fmt.Errorf("MinIO config not available") } case StorageAWSS3: if f.config.S3 != nil { storage, err = NewS3Storage(f.config.S3) } else { return nil, fmt.Errorf("S3 config not available") } case StorageOSS: if f.config.OSS != nil { storage, err = NewOSSStorage(f.config.OSS) } else { return nil, fmt.Errorf("OSS config not available") } default: return nil, fmt.Errorf("unsupported storage type: %v", storageType) } if err != nil { return nil, err } return storage, nil } // SetStorage sets the storage instance (useful for testing) func (f *StorageFactory) SetStorage(storage Storage) { f.mu.Lock() defer f.mu.Unlock() f.storage = storage } // StorageTypeMapping returns the storage type mapping (equivalent to Python's storage_mapping) var StorageTypeMapping = map[StorageType]func(*server.StorageConfig) (Storage, error){ StorageMinio: func(config *server.StorageConfig) (Storage, error) { if config.Minio == nil { return nil, fmt.Errorf("MinIO config not available") } return NewMinioStorage(config.Minio) }, StorageAWSS3: func(config *server.StorageConfig) (Storage, error) { if config.S3 == nil { return nil, fmt.Errorf("S3 config not available") } return NewS3Storage(config.S3) }, StorageOSS: func(config *server.StorageConfig) (Storage, error) { if config.OSS == nil { return nil, fmt.Errorf("OSS config not available") } return NewOSSStorage(config.OSS) }, }