Sonodex 开发企划,技术架构与实现规范 (v1.0)

1. 项目概述

Sonodex 是一款专为音乐制作人设计的本地 MIDI 与音频采样管理系统。其核心任务是高效索引、检索并管理分布在本地磁盘上的数十万计媒体素材,提供秒级的搜索响应,并确保数据状态与物理文件的高度一致性。

1.1 核心原则

  • 稳定性优先: 拒绝隐式缓存,所有数据变更必须透明且可追溯。
  • 性能导向: 针对 100,000+ 记录优化,确保 UI 线程永不阻塞。
  • 数据主权: 采用开放格式的 SQL 数据库,不依赖黑盒框架。

2. 技术栈选型 (Tech Stack)

维度技术选型说明
开发平台macOS 14.0+针对 Apple Silicon 与原生系统特性优化。
编程语言Swift 5.9+利用强类型、值类型语义与并发模型(Concurrency)。
UI 框架SwiftUI声明式 UI,处理状态驱动的复杂视图。
持久化层GRDB.swift (SQLite)放弃 SwiftData,选择类型安全的原生 SQL 包装器。
并发处理Swift Concurrency使用 async/await 处理文件 IO 与重型检索。

3. 系统架构设计

系统采用 层级解耦架构,确保数据库持久层与 UI 表现层之间有明确的边界,彻底消除“幽灵缓存”。

3.1 实体模型 (Entity Model)

弃用 Class 引用语义,全案使用 Value-based Struct

struct SonodexEntry: Codable, FetchableRecord, MutablePersistableRecord {
    var id: Int64?
    var fileName: String      // 文件名(索引核心)
    var relativePath: String  // 相对路径/绝对路径
    var duration: Double      // 音频长度
    var fileType: String      // wav, mid, aif 等
    var tags: String?         // 预留标签字段
    var bookmarkData: Data?   // macOS 权限持久化(重要)
}

4. 持久化层实现路径 (The SQL Path)

4.1 数据库初始化与迁移

使用 DatabasePool 以支持多线程并发读取,通过 DatabaseMigrator 管理 Schema 版本。

class DatabaseManager {
    static let shared = DatabaseManager()
    let dbPool: DatabasePool

    private init() {
        // 配置数据库存放于 Application Support
        let path = try! FileManager.default
            .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            .appendingPathComponent("sonodex.sqlite").path
        dbPool = try! DatabasePool(path: path)
        try! setupMigrations()
    }

    private func setupMigrations() throws {
        var migrator = DatabaseMigrator()
        migrator.registerMigration("v1_create_entries") { db in
            try db.create(table: "sonodex_entries") { t in
                t.autoIncrementedPrimaryKey("id")
                t.column("fileName", .text).notNull().indexed()
                t.column("relativePath", .text).notNull().unique()
                t.column("duration", .double)
                t.column("fileType", .text)
            }
        }
        try migrator.migrate(dbPool)
    }
}

4.2 高性能检索策略 (FTS5)

针对数十万条记录,传统的 LIKE 查询在大规模文本下表现不佳。Sonodex 必须启用 SQLite 的 FTS5 (Full-Text Search) 扩展模块。

  • 实现方式: 建立虚拟表(Virtual Table),将文件名映射至全文搜索索引。
  • 预期性能: 50 万条记录下,关键词检索耗时控制在 10ms 以内。

5. 关键技术方案

5.1 权限与路径一致性

macOS 的沙盒机制可能导致路径失效。

  • 解决方案: 存储 Security-Scoped Bookmarks。即使外部文件夹重命名,只要文件 UUID 未变,Sonodex 依然能通过 Data 重新解析出正确的 URL。

5.2 零缓存 UI 更新

使用 GRDB 的 ValueObservation

  • 机制: 订阅 SQLite 的事务提交通知。当文件扫描器(Scanner)在后台写入新采样时,UI 自动触发重新查询。
  • 隔离: 查询结果通过 map 转换为视图快照(Snapshot Structs),确保 View 层无法意外修改数据库实体。

6. 开发平台与环境建议

  • IDE: Xcode 15.0+。
  • 数据库调试工具: 推荐使用 TablePlus。它能直接打开 .sqlite 文件,实时监控扫描器写入的数据流。
  • 性能监控: 利用 Xcode Instruments 的 Core Data (SQLite) 工具 观察 IO 峰值和查询耗时。

7. 下一步实施方案

  1. 基础设施搭建: 在 Xcode 引入 GRDB 框架并配置 DatabaseManager 单例。
  2. Schema 迁移: 将原 Python (LMA) 的字段映射至 Swift Struct。
  3. 扫描引擎开发: 实现基于 FileManager 的递归扫描,并使用 dbPool.write 进行批量异步入库。
  4. FTS5 集成: 为搜索框添加全文检索能力。