# 模块解耦重构文档

## 概述

本次重构针对 `IndexBuilder` 和 `IndexLoader` 与 `vector_store_manager` 的高耦合问题，引入了以下三个核心优化方案：

1. **事件总线机制**：解耦组件间通信
2. **策略模式存储层**：支持多种存储后端热切换
3. **统一结果格式**：避免不同方法返回格式差异

## 一、事件总线系统

### 1.1 架构设计

事件总线采用发布-订阅模式，实现组件间的解耦通信：

```python
from src.events import EventBus, IndexBuildEvent

# 获取事件总线实例
event_bus = EventBus.get_instance()

# 订阅事件
def on_build_completed(event):
    print(f"索引构建完成: {event.data}")

event_bus.subscribe(EventType.INDEX_BUILD_COMPLETED, on_build_completed)

# 发布事件
event_bus.publish(
    IndexBuildEvent.build_completed(
        index_type="vector",
        nodes_count=100,
        duration=5.2
    )
)
```

### 1.2 事件类型

系统定义了以下事件类型：

**索引构建事件**
- `INDEX_BUILD_STARTED`: 索引构建开始
- `INDEX_BUILD_COMPLETED`: 索引构建完成
- `INDEX_BUILD_FAILED`: 索引构建失败

**索引加载事件**
- `INDEX_LOAD_STARTED`: 索引加载开始
- `INDEX_LOAD_COMPLETED`: 索引加载完成
- `INDEX_LOAD_FAILED`: 索引加载失败

**存储事件**
- `STORAGE_PERSISTED`: 存储持久化
- `STORAGE_DELETED`: 存储删除
- `STORAGE_SWITCHED`: 存储后端切换

**查询事件**
- `QUERY_STARTED`: 查询开始
- `QUERY_COMPLETED`: 查询完成
- `QUERY_FAILED`: 查询失败

### 1.3 使用示例

```python
from src.events import EventBus, EventType, StorageEvent

event_bus = EventBus.get_instance()

# 监控存储切换事件
def on_storage_switched(event):
    print(f"存储后端已切换: {event.data['from_backend']} -> {event.data['to_backend']}")

event_bus.subscribe(EventType.STORAGE_SWITCHED, on_storage_switched)

# 查看事件历史
history = event_bus.get_history(EventType.INDEX_BUILD_COMPLETED, limit=5)
for event in history:
    print(f"{event.timestamp}: {event.data}")
```

## 二、存储策略模式

### 2.1 架构设计

使用策略模式实现存储层抽象，支持运行时切换存储后端：

```
StorageProvider (提供者)
    ↓
StorageStrategy (抽象策略)
    ↓
    ├── LocalStorageStrategy (本地存储)
    └── QdrantStorageStrategy (Qdrant存储)
```

### 2.2 核心组件

**StorageStrategy（抽象基类）**
```python
class StorageStrategy(ABC):
    @abstractmethod
    def initialize(self) -> OperationResult:
        """初始化存储"""
        pass
    
    @abstractmethod
    def build_index(self, nodes: List[BaseNode]) -> Optional[VectorStoreIndex]:
        """构建索引"""
        pass
    
    @abstractmethod
    def load_index(self) -> Optional[VectorStoreIndex]:
        """加载索引"""
        pass
    
    @abstractmethod
    def persist(self, index: VectorStoreIndex) -> OperationResult:
        """持久化索引"""
        pass
```

**StorageProvider（存储提供者）**
```python
class StorageProvider:
    """
    存储提供者（单例）
    - 根据配置创建合适的存储策略
    - 支持运行时切换存储后端
    - 管理存储策略的生命周期
    """
```

### 2.3 使用示例

#### 基本使用

```python
from src.storage.strategies import StorageProvider
from src.types import StorageBackend

# 获取存储提供者
provider = StorageProvider.get_instance()
provider.setup(config)

# 获取当前存储策略
strategy = provider.get_current_strategy()

# 构建索引
index = strategy.build_index(nodes)

# 持久化索引
result = strategy.persist(index)
```

#### 切换存储后端

```python
from src.storage.strategies import StorageProvider
from src.types import StorageBackend

provider = StorageProvider.get_instance()

# 切换到Qdrant
success = provider.switch_backend(StorageBackend.QDRANT)

# 切换到本地存储
success = provider.switch_backend(StorageBackend.LOCAL)
```

#### 使用特定后端

```python
# 获取本地存储策略
local_strategy = provider.get_strategy(StorageBackend.LOCAL)
local_index = local_strategy.build_index(nodes)

# 获取Qdrant存储策略
qdrant_strategy = provider.get_strategy(StorageBackend.QDRANT)
qdrant_index = qdrant_strategy.build_index(nodes)
```

## 三、统一结果格式

### 3.1 架构设计

所有操作统一使用结果对象，确保返回格式一致：

```python
from src.types import Result, IndexResult, QueryResult, OperationResult
```

### 3.2 结果类型

**Result[T]（通用结果）**
```python
result = Result.ok(data=some_value, message="操作成功")
result = Result.fail(error="错误信息", message="操作失败")
result = Result.partial(data=some_value, message="部分成功")
result = Result.skip(message="操作已跳过")

if result.is_ok():
    print(result.data)
```

**IndexResult（索引操作结果）**
```python
result = IndexResult.ok(
    index=vector_index,
    nodes_count=100,
    index_type="vector",
    duration=5.2
)

if result.success:
    print(f"索引构建完成: {result.nodes_count} 个节点，耗时 {result.duration}s")
    index = result.index
```

**QueryResult（查询结果）**
```python
result = QueryResult.ok(
    response=response,
    query_text="查询文本",
    retrieval_mode="hybrid",
    duration=1.5
)

if result.success:
    print(f"查询完成: {len(result.results)} 个结果，耗时 {result.duration}s")
```

**OperationResult（操作结果）**
```python
result = OperationResult.ok(data=True, message="操作成功")
result = OperationResult.fail(error="错误信息")

if result.success:
    print(result.message)
```

### 3.3 使用示例

#### IndexBuilder 使用

```python
from src.core import IndexBuilder

builder = IndexBuilder(config)

# 构建向量索引 - 返回 IndexResult
result = builder.build_vector_index(nodes)
if result.success:
    print(f"索引类型: {result.index_type}")
    print(f"节点数: {result.nodes_count}")
    print(f"耗时: {result.duration}s")
    vector_index = result.index
else:
    print(f"构建失败: {result.error}")

# 构建所有索引 - 返回 IndexResult
result = builder.build_all_indexes(data_dir="./data", force_rebuild=False)
if result.success:
    print(f"索引类型: {result.index_type}")
    print(f"是否跳过: {result.is_skip()}")
```

#### IndexLoader 使用

```python
from src.core import IndexLoader

loader = IndexLoader(config)

# 加载向量索引 - 返回 IndexResult
result = loader.load_vector_index()
if result.success:
    vector_index = result.index
    print(f"加载成功，耗时: {result.duration}s")
else:
    print(f"加载失败: {result.error}")

# 加载所有索引 - 返回 IndexResult
result = loader.load_all_indexes()
if result.success:
    index = result.index
```

## 四、重构前后对比

### 4.1 IndexBuilder

**重构前：**
```python
class IndexBuilder:
    def __init__(self, config):
        self.vector_store_manager = VectorStoreManager(config)  # 直接耦合
        self.bm25_store_manager = BM25StoreManager(config)
    
    def build_vector_index(self, nodes) -> Optional[VectorStoreIndex]:
        # 直接操作 vector_store_manager
        vector_store = self.vector_store_manager.setup_qdrant()
        # ... 返回 Optional[VectorStoreIndex]
        return index  # or None
    
    def build_all_indexes(self, data_dir, force_rebuild) -> tuple:
        # 返回元组 (bool, Optional[VectorStoreIndex])
        return True, index  # 格式不统一
```

**重构后：**
```python
class IndexBuilder:
    def __init__(self, config):
        self.storage_provider = StorageProvider.get_instance()  # 使用策略提供者
        self.bm25_store_manager = BM25StoreManager(config)
        self.event_bus = EventBus.get_instance()  # 事件总线
    
    def build_vector_index(self, nodes) -> IndexResult:
        # 使用策略模式
        strategy = self.storage_provider.get_current_strategy()
        index = strategy.build_index(nodes)
        
        # 发布事件
        self.event_bus.publish(IndexBuildEvent.build_completed(...))
        
        # 返回统一格式
        return IndexResult.ok(index=index, nodes_count=len(nodes), ...)
    
    def build_all_indexes(self, data_dir, force_rebuild) -> IndexResult:
        # 返回统一的 IndexResult
        return IndexResult.ok(...)
```

### 4.2 IndexLoader

**重构前：**
```python
class IndexLoader:
    def __init__(self, config):
        self.vector_store_manager = VectorStoreManager(config)  # 直接耦合
    
    def load_vector_index(self) -> Optional[VectorStoreIndex]:
        # 直接操作 vector_store_manager
        vector_store = self.vector_store_manager.get_vector_store()
        # ... 返回 Optional[VectorStoreIndex]
        return index  # or None
```

**重构后：**
```python
class IndexLoader:
    def __init__(self, config):
        self.storage_provider = StorageProvider.get_instance()  # 使用策略提供者
        self.event_bus = EventBus.get_instance()  # 事件总线
    
    def load_vector_index(self) -> IndexResult:
        # 使用策略模式
        strategy = self.storage_provider.get_current_strategy()
        index = strategy.load_index()
        
        # 发布事件
        self.event_bus.publish(IndexLoadEvent.load_completed(...))
        
        # 返回统一格式
        return IndexResult.ok(index=index, ...)
```

## 五、依赖注入集成

### 5.1 新增服务提供者

```python
# src/di/providers.py

class EventServiceProvider(ServiceProvider):
    """事件服务提供者"""
    def register(self, container):
        container.register_singleton("event_bus", lambda: EventBus.get_instance())

class StorageServiceProvider(ServiceProvider):
    """存储服务提供者"""
    def register(self, container):
        def create_storage_provider():
            provider = StorageProvider.get_instance()
            config = container.get("config")
            provider.setup(config)
            return provider
        container.register_singleton("storage_provider", create_storage_provider)
```

### 5.2 使用示例

```python
from src.di import get_container

container = get_container()

# 获取事件总线
event_bus = container.get("event_bus")

# 获取存储提供者
storage_provider = container.get("storage_provider")

# 获取配置
config = container.get("config")
```

## 六、优势总结

### 6.1 解耦优势

1. **组件独立性**：`IndexBuilder` 和 `IndexLoader` 不再直接依赖 `VectorStoreManager`
2. **可测试性**：可以轻松模拟（mock）存储策略进行单元测试
3. **可扩展性**：新增存储后端只需实现 `StorageStrategy` 接口

### 6.2 策略模式优势

1. **热切换**：运行时切换存储后端，无需重启应用
2. **配置驱动**：通过配置文件控制使用的存储后端
3. **统一接口**：所有存储后端提供相同的操作接口

### 6.3 事件总线优势

1. **监控能力**：可以订阅事件实现监控和日志
2. **功能扩展**：新增功能只需订阅相关事件，无需修改核心代码
3. **调试支持**：事件历史记录有助于问题排查

### 6.4 统一结果格式优势

1. **一致性**：所有操作返回格式统一，易于理解和使用
2. **信息完整**：包含成功/失败状态、数据、错误信息、元数据等
3. **类型安全**：使用泛型和数据类提供类型提示

## 七、迁移指南

### 7.1 更新代码

**旧代码：**
```python
builder = IndexBuilder(config)
success, index = builder.build_all_indexes(data_dir, force_rebuild=True)
if success and index:
    # 使用 index
```

**新代码：**
```python
builder = IndexBuilder(config)
result = builder.build_all_indexes(data_dir, force_rebuild=True)
if result.success:
    index = result.index
    print(f"构建完成，耗时: {result.duration}s")
```

### 7.2 监听事件

```python
from src.events import EventBus, EventType

event_bus = EventBus.get_instance()

def on_index_build_completed(event):
    print(f"索引构建完成: {event.data}")
    # 可以在这里执行额外操作，如发送通知

event_bus.subscribe(EventType.INDEX_BUILD_COMPLETED, on_index_build_completed)
```

### 7.3 切换存储后端

```python
from src.storage.strategies import StorageProvider
from src.types import StorageBackend

provider = StorageProvider.get_instance()

# 切换到 Qdrant
if provider.switch_backend(StorageBackend.QDRANT):
    print("已切换到 Qdrant 存储")
    
# 切换回本地存储
if provider.switch_backend(StorageBackend.LOCAL):
    print("已切换到本地存储")
```

## 八、注意事项

1. **向后兼容**：旧的 `VectorStoreManager` 和 `BM25StoreManager` 仍然保留，确保现有代码兼容
2. **渐进式迁移**：建议逐步将代码迁移到新架构
3. **配置要求**：确保配置文件包含正确的存储后端设置
4. **事件订阅**：事件处理器应避免执行耗时操作，以免阻塞事件分发

## 九、未来扩展

### 9.1 新增存储后端

要添加新的存储后端（如 Redis、Elasticsearch），只需：

1. 实现 `StorageStrategy` 接口
2. 在 `StorageProvider` 中注册新策略
3. 更新 `StorageBackend` 枚举

示例：
```python
class RedisStorageStrategy(StorageStrategy):
    def initialize(self) -> OperationResult:
        # 实现 Redis 初始化
        pass
    
    def build_index(self, nodes) -> Optional[VectorStoreIndex]:
        # 实现 Redis 索引构建
        pass
    
    # ... 实现其他方法
```

### 9.2 新增事件类型

要添加新的事件类型，只需：

1. 在 `EventType` 枚举中添加新事件
2. 在 `events.py` 中创建对应的事件类

示例：
```python
class EventType(Enum):
    # ... 现有事件
    CACHE_INVALIDATED = "cache_invalidated"

@dataclass
class CacheEvent(Event):
    @staticmethod
    def invalidated(cache_key: str) -> "CacheEvent":
        return CacheEvent(
            event_type=EventType.CACHE_INVALIDATED,
            data={"cache_key": cache_key}
        )
```

## 十、总结

本次重构通过引入事件总线、策略模式和统一结果格式，成功解决了模块间的高耦合问题，提升了系统的：

- ✅ **可维护性**：代码结构更清晰，职责分离明确
- ✅ **可扩展性**：易于添加新的存储后端和功能
- ✅ **可测试性**：组件解耦，便于单元测试
- ✅ **灵活性**：支持运行时切换存储后端
- ✅ **一致性**：统一的API和返回格式

这些改进为系统的长期演进奠定了坚实的基础。
