forked from lnreader/lnreader
-
Notifications
You must be signed in to change notification settings - Fork 0
Optimize import #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
CD-Z
wants to merge
21
commits into
master
Choose a base branch
from
optimize-import
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Optimize import #35
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
1ca9a67
perf: Optimize Background Task Memory Usage and Lifecycle Management …
CD-Z 7064597
feat: Add Optional Continue Reading Buttons To Library
rajarsheechatterjee 2ad4620
chore: Release v2.0.0
rajarsheechatterjee adc8a12
Optimize backup restore transactions
CD-Z 9199598
perf(backup): optimize restore batching and archives
CD-Z dd81bbf
Optimize backup restore pipeline
CD-Z 2ba2fd1
Extract novel restore queries
CD-Z 9ea934f
Improve backup restore handling
CD-Z 2a30d79
Fix backup restore and ZIP edge cases
CD-Z 1ebebe3
fix: harden backup restore and archive handling
CD-Z db21e49
fix: discard orphan chapters safely
CD-Z 3844d00
fix failing test
CD-Z 462bfb3
Improve backup restore telemetry
CD-Z 0d625c4
Port restore batching from PR #2080
CD-Z 0bcee9e
test(db): match SQLite batch error messages
CD-Z ca0cace
perf(backup): remove redundant restore validation
CD-Z 794c67b
feat(backup): report progress through restore phases
CD-Z def67de
feat(backup): show restored novel totals
CD-Z a75ac1b
Unify drive + selfhost + local
CD-Z 70b5f27
Performance tracking
CD-Z 73fd805
remove unneeded
CD-Z File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ## Backup restore benchmark: v2 vs v3 | ||
|
|
||
| Compared the legacy v2 backup (`1.bench.zip`) with the new v3 backup (`2.bench.zip`). Both runs restored **7,323 novels** with **0 failures**, 9 categories, and 14 plugins. | ||
|
|
||
| ### End-to-end result | ||
|
|
||
| | Metric | Legacy v2 | New v3 | Change | | ||
| |---|---:|---:|---:| | ||
| | Total restore time | 5m 15.6s | 4m 11.0s | **64.7s faster (20.5%)** | | ||
|
|
||
| Total time is measured from `local:start` through `local:finalize:done`. | ||
|
|
||
| ### Restore phases | ||
|
|
||
| | Phase | Legacy v2 | New v3 | Change | | ||
| |---|---:|---:|---:| | ||
| | Copy | 12.8s | 13.2s | 0.5s slower | | ||
| | Outer unzip | 46.3s | 30.2s | **16.1s faster (34.7%)** | | ||
| | Novel validation | 46.7s | 24.9s | **21.9s faster (46.8%)** | | ||
| | Novel restore loop | 206.8s | 179.0s | **27.8s faster (13.4%)** | | ||
|
|
||
| ### Novel restore timing breakdown | ||
|
|
||
| | Operation | Legacy v2 | New v3 | Change | | ||
| |---|---:|---:|---:| | ||
| | Read | 52.5s | 16.6s | **35.9s faster (68.4%)** | | ||
| | Parse | 45.5s | 32.7s | **12.8s faster (28.2%)** | | ||
| | Database | 135.5s | 136.7s | 1.3s slower (0.9%) | | ||
| | Covers | 19.6s | 17.8s | 1.8s faster (9.0%) | | ||
|
|
||
| The v3 run reduced end-to-end restore time by **about one minute**. The largest per-operation improvement was reading novel data, while database time was effectively unchanged. The phase durations and per-operation timings are reported separately from the benchmark logs; the operation timings should not be summed as if they were sequential phases. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| CREATE TABLE `RestoreChapterMapping` ( | ||
| `restoreRunId` text NOT NULL, | ||
| `backupNovelId` integer NOT NULL, | ||
| `backupChapterId` integer NOT NULL, | ||
| `restoredNovelId` integer NOT NULL, | ||
| `restoredChapterId` integer NOT NULL, | ||
| CONSTRAINT `fk_RestoreChapterMapping_restoredNovelId_Novel_id_fk` FOREIGN KEY (`restoredNovelId`) REFERENCES `Novel`(`id`) ON DELETE CASCADE, | ||
| CONSTRAINT `fk_RestoreChapterMapping_restoredChapterId_Chapter_id_fk` FOREIGN KEY (`restoredChapterId`) REFERENCES `Chapter`(`id`) ON DELETE CASCADE | ||
| ); | ||
| --> statement-breakpoint | ||
| PRAGMA foreign_keys=OFF;--> statement-breakpoint | ||
| CREATE TABLE `__new_Chapter` ( | ||
| `id` integer PRIMARY KEY AUTOINCREMENT, | ||
| `novelId` integer NOT NULL, | ||
| `path` text NOT NULL, | ||
| `name` text NOT NULL, | ||
| `releaseTime` text, | ||
| `bookmark` integer DEFAULT false, | ||
| `unread` integer DEFAULT true, | ||
| `readTime` text, | ||
| `isDownloaded` integer DEFAULT false, | ||
| `updatedTime` text, | ||
| `chapterNumber` real, | ||
| `page` text DEFAULT '1', | ||
| `position` integer DEFAULT 0, | ||
| `progress` integer, | ||
| `scanlator` text, | ||
| `timeSpent` integer DEFAULT 0, | ||
| CONSTRAINT `fk_Chapter_novelId_Novel_id_fk` FOREIGN KEY (`novelId`) REFERENCES `Novel`(`id`) ON DELETE CASCADE | ||
| ); | ||
| --> statement-breakpoint | ||
| -- Preserve the previous AUTOINCREMENT high-water mark across the rebuild. | ||
| CREATE TEMP TABLE `__chapter_sequence` AS | ||
| SELECT COALESCE(MAX(`seq`), 0) AS `seq` | ||
| FROM `sqlite_sequence` | ||
| WHERE `name` = 'Chapter'; | ||
| --> statement-breakpoint | ||
| -- Chapters without a novel are invalid legacy data and are intentionally discarded. | ||
| INSERT INTO `__new_Chapter`(`id`, `novelId`, `path`, `name`, `releaseTime`, `bookmark`, `unread`, `readTime`, `isDownloaded`, `updatedTime`, `chapterNumber`, `page`, `position`, `progress`, `scanlator`, `timeSpent`) SELECT `id`, `novelId`, `path`, `name`, `releaseTime`, `bookmark`, `unread`, `readTime`, `isDownloaded`, `updatedTime`, `chapterNumber`, `page`, `position`, `progress`, `scanlator`, `timeSpent` FROM `Chapter` WHERE EXISTS (SELECT 1 FROM `Novel` WHERE `Novel`.`id` = `Chapter`.`novelId`);--> statement-breakpoint | ||
| DROP TABLE `Chapter`;--> statement-breakpoint | ||
| ALTER TABLE `__new_Chapter` RENAME TO `Chapter`;--> statement-breakpoint | ||
| INSERT INTO `sqlite_sequence` (`name`, `seq`) | ||
| SELECT 'Chapter', `seq` FROM `__chapter_sequence` | ||
| WHERE NOT EXISTS ( | ||
| SELECT 1 FROM `sqlite_sequence` WHERE `name` = 'Chapter' | ||
| ); | ||
| --> statement-breakpoint | ||
| UPDATE `sqlite_sequence` | ||
| SET `seq` = MAX(`seq`, (SELECT `seq` FROM `__chapter_sequence`)) | ||
| WHERE `name` = 'Chapter'; | ||
| --> statement-breakpoint | ||
| DROP TABLE `__chapter_sequence`; | ||
| --> statement-breakpoint | ||
| PRAGMA foreign_keys=ON;--> statement-breakpoint | ||
| CREATE UNIQUE INDEX `chapter_novel_path_unique` ON `Chapter` (`novelId`,`path`);--> statement-breakpoint | ||
| CREATE INDEX `chapterNovelIdIndex` ON `Chapter` (`novelId`,`position`,`page`,`id`);--> statement-breakpoint | ||
| CREATE UNIQUE INDEX `restore_chapter_mapping_unique` ON `RestoreChapterMapping` (`restoreRunId`,`backupNovelId`,`backupChapterId`);--> statement-breakpoint | ||
| CREATE INDEX `restore_chapter_mapping_novel_index` ON `RestoreChapterMapping` (`restoreRunId`,`backupNovelId`); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🔎 Supported by static analysis
🏁 Script executed:
Repository: CD-Z/lnreader
Length of output: 2512
🏁 Script executed:
Repository: CD-Z/lnreader
Length of output: 29936
🌐 Web query:
Drizzle ORM 1.0.0-beta.22 migrate SQLite transaction implementation PRAGMA foreign_keys💡 Result:
<source_evidence>
Citations:
🏁 Script executed:
Repository: CD-Z/lnreader
Length of output: 27840
🌐 Web query:
Drizzle ORM op-sqlite migrator 1.0.0-beta.22 BEGIN COMMIT migration source💡 Result:
<source_evidence>
Citations:
Handle orphan
Chapter.novelIdvalues before the table copy.initializeDatabaseenables foreign-key enforcement before calling themigratefunction fromdrizzle-orm/op-sqlite/migrator. The OP-SQLite migrator runs migration statements in a transaction, and SQLite ignoresPRAGMA foreign_keys=OFFinside that transaction. Therefore, theINSERT ... SELECTat line 32 enforces the new foreign key. If any existingChapterrow has no matchingNovel, the migration can fail withFOREIGN KEY constraint failed, preventing startup.Add explicit orphan-row repair or retention handling before the copy. Do not delete rows unconditionally without an approved data-retention policy.
🤖 Prompt for AI Agents