diff --git a/.kilo/plans/1775535760568-brave-panda.md b/.kilo/plans/1775535760568-brave-panda.md new file mode 100644 index 00000000..7e4fb48a --- /dev/null +++ b/.kilo/plans/1775535760568-brave-panda.md @@ -0,0 +1,170 @@ +# Kế hoạch chuyển đổi Komga từ SQLite sang PostgreSQL + +## Mục tiêu +Thêm hỗ trợ PostgreSQL cho Komga, cho phép người dùng lựa chọn database engine (SQLite hoặc PostgreSQL) thông qua cấu hình. Vẫn giữ backward compatibility với SQLite (mặc định). + +## Hiện trạng +- Dự án hiện chỉ hỗ trợ SQLite. +- Cấu hình database trong `KomgaProperties.Database` chỉ có thuộc tính `file` (đường dẫn file SQLite). +- DataSource sử dụng `SqliteUdfDataSource` với các UDF và collation đặc thù. +- JOOQ dialect cố định `SQLDialect.SQLITE`. +- Flyway migration chỉ có thư mục `sqlite`. +- Code DAO sử dụng nhiều `collate(SqliteUdfDataSource.COLLATION_UNICODE_3)` và `udfStripAccents()`. +- Build Gradle cấu hình jooq generation chỉ cho SQLite. + +## Phạm vi thay đổi +1. **Cấu hình database động**: Thêm thuộc tính `type` (sqlite/postgresql) và các thuộc tính kết nối. +2. **DataSourcesConfiguration**: Tạo DataSource tương ứng với database type. +3. **Abstract UDF/Collation**: Tạo interface cung cấp UDF và collation phù hợp với dialect. +4. **Flyway migration cho PostgreSQL**: Tạo thư mục migration PostgreSQL, chuyển đổi toàn bộ migration hiện tại. +5. **JOOQ configuration động**: Dialect và code generation cho cả hai database. +6. **Cập nhật code DAO**: Sử dụng abstract UDF/collation. +7. **Cập nhật build.gradle.kts**: Thêm dependency PostgreSQL, mở rộng jooq configuration. +8. **Testing**: Đảm bảo hoạt động với cả hai database. + +## Sprint 1: Cơ sở hạ tầng và cấu hình (Tuần 1) + +### 1.1. Thêm dependency PostgreSQL +- Thêm runtime dependency `org.postgresql:postgresql` vào `build.gradle.kts`. +- Thêm `jooqGenerator` dependency tương ứng. +- Giữ SQLite làm mặc định. + +### 1.2. Mở rộng KomgaProperties.Database +- Thêm enum `DatabaseType { SQLITE, POSTGRESQL }`. +- Thêm thuộc tính `type: DatabaseType = SQLITE`. +- Thêm thuộc tính `url`, `username`, `password`, `driverClassName` (optional). +- Giữ thuộc tính `file` cho SQLite (backward compatibility). +- Xử lý logic: nếu `file` được cung cấp và `type` không set, mặc định là SQLite; nếu `url` chứa `jdbc:postgresql://` thì type là PostgreSQL. + +### 1.3. Cập nhật DataSourcesConfiguration +- Tách `buildDataSource` thành hai phiên bản: `buildSqliteDataSource` và `buildPostgresDataSource`. +- Chọn phiên bản dựa trên `database.type`. +- Với PostgreSQL: sử dụng `DataSourceBuilder` với driver PostgreSQL, không có pragmas/journal mode. +- Với SQLite: giữ nguyên logic hiện tại. +- Tạo bean DataSource tương ứng. + +### 1.4. Tạo abstract UDF/Collation provider +- Tạo interface `DatabaseDialectProvider` với các method: `collationUnicode3()`, `regexpFunction()`, `stripAccentsFunction()`. +- Tạo implementation cho SQLite (`SqliteDialectProvider`) và PostgreSQL (`PostgresDialectProvider`). +- PostgreSQL: sử dụng extension `unaccent` cho strip accents, collation ICU cho unicode collation, toán tử `~*` cho regexp. +- Đăng ký bean tương ứng với database type. + +### 1.5. Cập nhật KomgaJooqConfiguration +- Inject `KomgaProperties` để lấy `database.type`. +- Set dialect động: `SQLDialect.SQLITE` hoặc `SQLDialect.POSTGRES`. +- Cập nhật `createDslContext` để sử dụng dialect phù hợp. + +### 1.6. Cập nhật cấu hình Flyway +- `spring.flyway.locations` hiện dùng `{vendor}` sẽ tự động chọn thư mục `postgresql` khi dialect là PostgreSQL. +- Đảm bảo Flyway detect đúng vendor. + +### Deliverables Sprint 1 +- Dependency PostgreSQL được thêm. +- Cấu hình database type hoạt động. +- DataSources tạo đúng với PostgreSQL. +- Abstract dialect provider. +- JOOQ dialect động. +- Các unit test cơ bản cho cấu hình. + +## Sprint 2: Migration database và JOOQ generation (Tuần 2) + +### 2.1. Tạo thư mục migration PostgreSQL +- Tạo `src/flyway/resources/db/migration/postgresql/`. +- Tạo `src/flyway/kotlin/db/migration/postgresql/`. +- Chuyển đổi toàn bộ migration SQLite sang PostgreSQL. + +### 2.2. Chuyển đổi migration scripts +- Chuyển đổi kiểu dữ liệu: + - `boolean` → `boolean` + - `datetime` → `timestamptz` (hoặc `timestamp`) + - `int8` → `bigint` + - `varchar` → `text` hoặc `varchar(n)` + - `blob` → `bytea` +- Điều chỉnh syntax: `CREATE INDEX IF NOT EXISTS` → `CREATE INDEX IF NOT EXISTS` (PostgreSQL 9.5+ hỗ trợ). +- Các ràng buộc khóa ngoại: `FOREIGN KEY (...) REFERENCES ...` giữ nguyên. +- Các migration Kotlin: đảm bảo SQL tương thích cả hai dialect (có thể dùng Flyway's `@DatabaseType` hoặc tách riêng). + +### 2.3. Cập nhật build.gradle.kts cho JOOQ generation +- Thêm jooq configuration cho PostgreSQL: + - Driver: `org.postgresql.Driver` + - URL: kết nối đến PostgreSQL test instance (có thể dùng Testcontainers). + - Database: `org.jooq.meta.postgres.PostgresDatabase` +- Tạo task `generateJooqPostgres` riêng. +- Có thể generate code vào package riêng: `org.gotson.komga.jooq.main.postgres`. + +### 2.4. Cập nhật code generation workflow +- Hiện tại jooq generation dựa trên SQLite schema được tạo bởi Flyway migration. +- Với PostgreSQL, cần chạy migration PostgreSQL trên test database rồi generate. +- Có thể sử dụng Testcontainers PostgreSQL trong quá trình build. + +### 2.5. Cập nhật tasks database +- Tasks database hiện cũng dùng SQLite. Có thể giữ nguyên SQLite (đơn giản) hoặc hỗ trợ PostgreSQL. +- Quyết định: giữ SQLite cho tasks (không cần scale), nhưng cấu hình cho phép chung nếu muốn. + +### Deliverables Sprint 2 +- Toàn bộ migration PostgreSQL. +- JOOQ generation thành công cho PostgreSQL. +- Tasks database được xử lý phù hợp. +- Có thể khởi động ứng dụng với PostgreSQL (chưa có UDF/collation). + +## Sprint 3: Cập nhật code DAO và testing (Tuần 3) + +### 3.1. Thay thế sử dụng UDF/collation trong DAO +- Cập nhật file Utils.kt: `Field.udfStripAccents()` sử dụng `DatabaseDialectProvider`. +- Cập nhật các file DAO: thay `collate(SqliteUdfDataSource.COLLATION_UNICODE_3)` bằng `collate(dialectProvider.collationUnicode3())`. +- Cập nhật SeriesSearchHelper, BookSearchHelper, ReferentialDao, SeriesDtoDao, BookDtoDao, SeriesCollectionDao, ReadListDao. + +### 3.2. Xử lý REGEXP trong queries +- Tìm tất cả chỗ sử dụng `DSL.field("{0} REGEXP {1}", ...)` và thay bằng `dialectProvider.regexpFunction()`. +- Đảm bảo regexp syntax tương thích (PostgreSQL sử dụng `~*`). + +### 3.3. Cập nhật SqliteUdfDataSource +- Đổi tên thành `DialectAwareDataSource` hoặc giữ nguyên nhưng tách logic PostgreSQL. +- Hoặc tạo `PostgresUdfDataSource` riêng. + +### 3.4. Testing +- Tạo integration tests với Testcontainers PostgreSQL. +- Test tất cả các chức năng chính với cả hai database. +- Đảm bảo migration PostgreSQL chạy đúng. +- Test UDF/collation hoạt động tương đương. + +### 3.5. Documentation +- Cập nhật tài liệu cấu hình database. +- Hướng dẫn chuyển đổi từ SQLite sang PostgreSQL (migration tool có thể cần thiết). + +### 3.6. Migration tool cho dữ liệu hiện có +- Có thể phát triển tool export/import hoặc sử dụng pgloader. +- Không nằm trong phạm vi chính nhưng cần xem xét. + +### Deliverables Sprint 3 +- Code DAO hoạt động với cả hai database. +- Integration tests pass. +- Documentation cập nhật. +- Ứng dụng có thể chạy với PostgreSQL đầy đủ chức năng. + +## Rủi ro và phụ thuộc +1. **Hiệu năng**: PostgreSQL có thể khác SQLite, cần tuning. +2. **UDF/collation**: Đảm bảo chức năng tương đương. +3. **Migration phức tạp**: Số lượng migration lớn (91 files), cần chuyển đổi cẩn thận. +4. **Testing**: Cần thiết lập CI với cả hai database. + +## Các file chính cần sửa đổi +1. `komga/build.gradle.kts` +2. `komga/src/main/resources/application.yml` +3. `komga/src/main/kotlin/org/gotson/komga/infrastructure/configuration/KomgaProperties.kt` +4. `komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/DataSourcesConfiguration.kt` +5. `komga/src/main/kotlin/org/gotson/komga/infrastructure/datasource/SqliteUdfDataSource.kt` +6. `komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/KomgaJooqConfiguration.kt` +7. `komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/Utils.kt` +8. Các file DAO (SeriesDtoDao, ReferentialDao, ...) +9. Tạo thư mục `src/flyway/resources/db/migration/postgresql/` +10. Tạo `src/flyway/kotlin/db/migration/postgresql/` + +## Ước lượng công sức +- Sprint 1: 40 giờ +- Sprint 2: 60 giờ (do migration nhiều) +- Sprint 3: 50 giờ +- Tổng: ~150 giờ + +## Kết quả mong đợi +Komga hỗ trợ cả SQLite và PostgreSQL, người dùng có thể lựa chọn database phù hợp với nhu cầu scale. \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..edc55ceb --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "snyk.advanced.autoSelectOrganization": true +} \ No newline at end of file