Commit 0d9c7fd
authored
fix: DB readonly-rollback recovery + cooperative import cancellation (#255)
* fix(db): recover readonly-rollback databases on startup
A user who cancelled a large dive-computer import could no longer
launch the app: every startup failed with `SqliteException(776):
attempt to write a readonly database` on `PRAGMA user_version`.
Root cause: `getStoredSchemaVersion` opened the db with
`OpenMode.readOnly`. When a crashed/cancelled transaction had left a
hot journal behind, SQLite's automatic rollback needs write access;
a read-only open throws SQLITE_READONLY_ROLLBACK (extended code 776)
before the first PRAGMA can run.
Fix:
- Open RW in `getStoredSchemaVersion` so SQLite can auto-recover the
journal during the existence probe.
- Add `recoverHotJournal` + `isRecoverableReadonlyError` helpers as
defense-in-depth, and an explicit recovery screen on the startup
page ("Database needs recovery" → "Recover database" button) so
users who still hit a readonly-family exception get a one-tap path
instead of the actively-harmful "reinstall or contact support"
copy.
- Generic-error copy updated to make clear the data is still on disk.
Adds unit tests for the new DatabaseService helpers and widget tests
for all three recovery-UI states (required, recovering, failed).
* fix(import): cooperative cancellation via ImportCancellationToken
Previously, cancelling a large import (e.g. 300-dive Perdix download) showed
a "cannot be cancelled" dialog and the only option was to force-kill the app.
Killing mid-transaction left SQLite with a hot rollback journal, which caused
the next launch to hit SQLITE_READONLY_ROLLBACK (776) on PRAGMA user_version.
The wizard now offers a real Cancel button. Cancellation is polled cooperatively
at per-dive boundaries in DiveComputerAdapter, UddfEntityImporter, and
HealthKitAdapter, so the current dive finishes writing to its own transaction
before the loop breaks. Already-imported dives are kept. The fingerprint
advances only for dives that were actually processed, so the remainder can be
re-imported next session.
* fix(import): address PR #255 review feedback
- Remove dead importedDives variable in DiveComputerAdapter that was
only appended to, never read.
- Reset isCancellationRequested in the wizard's finally block so a
second import starts fresh instead of inheriting the stale flag.
- Localize "Cancel import" and "Cancelling..." on the progress step
via two new l10n keys (settings_import_cancelButton,
settings_import_cancelling) across all 11 supported locales.
* test: cover import cancel dialog + DB recovery-failed UI
Raise PR #255 patch coverage from 66% toward 85% by adding tests for
the branches introduced by the cancel/recovery work:
- UnifiedImportWizard cancel dialog (4 tests): confirm dialog opens,
Keep importing dismisses without cancelImport, Cancel import fires
cancelImport, already-cancelling notice renders instead of the
confirm dialog.
- ImportProgressStep cancel button wires through to cancelImport.
- StartupPage recoveryFailed UI: catch-block routing, Try again
re-invokes _runRecovery, Close invokes closeAppOverride.
Adds two @VisibleForTesting hooks to UnifiedImportWizard
(initialPageOverride, notifierFactoryOverride) so tests can jump to
the import-progress page and inject a spy notifier into the widget's
inner ProviderScope without driving the full bundle/import pipeline.
* fix: clear stale error in _runRecovery and show specific message on recover failure
When `DatabaseService.recoverHotJournal` returns false, the recoveryFailed
UI now surfaces a concrete message ("SQLite could not reopen the database
to roll back the interrupted transaction.") instead of leaving whatever
text `_errorMessage` last held. Also clears `_errorMessage` on entry to
the `recovering` state so a second attempt cannot leak text from the
previous failure into the next UI.
Adds a test that writes invalid SQLite bytes (0xAB) to exercise the
!recovered branch: the handle opens but `PRAGMA user_version` throws
SQLITE_NOTADB inside recoverHotJournal, which catches and returns false.
Addresses Copilot review comment on PR #255.1 parent 5381574 commit 0d9c7fd
47 files changed
Lines changed: 1609 additions & 32 deletions
File tree
- lib
- core
- presentation/pages
- services
- features
- dive_import/data/services
- import_wizard
- data/adapters
- domain
- adapters
- models
- presentation
- pages
- providers
- widgets
- l10n/arb
- test
- core
- presentation/pages
- services
- features/import_wizard
- data/adapters
- domain
- adapters
- models
- presentation
- pages
- providers
- widgets
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
46 | 50 | | |
47 | 51 | | |
48 | 52 | | |
| |||
99 | 103 | | |
100 | 104 | | |
101 | 105 | | |
| 106 | + | |
102 | 107 | | |
103 | 108 | | |
104 | 109 | | |
| |||
199 | 204 | | |
200 | 205 | | |
201 | 206 | | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
202 | 228 | | |
203 | 229 | | |
204 | 230 | | |
| |||
210 | 236 | | |
211 | 237 | | |
212 | 238 | | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
213 | 275 | | |
214 | 276 | | |
215 | 277 | | |
| |||
390 | 452 | | |
391 | 453 | | |
392 | 454 | | |
393 | | - | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
394 | 459 | | |
395 | 460 | | |
396 | 461 | | |
| |||
497 | 562 | | |
498 | 563 | | |
499 | 564 | | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
500 | 571 | | |
501 | 572 | | |
502 | 573 | | |
| |||
561 | 632 | | |
562 | 633 | | |
563 | 634 | | |
564 | | - | |
| 635 | + | |
| 636 | + | |
565 | 637 | | |
566 | 638 | | |
567 | 639 | | |
| |||
571 | 643 | | |
572 | 644 | | |
573 | 645 | | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
574 | 789 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
196 | 196 | | |
197 | 197 | | |
198 | 198 | | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
199 | 204 | | |
200 | 205 | | |
201 | 206 | | |
202 | 207 | | |
203 | | - | |
| 208 | + | |
204 | 209 | | |
205 | 210 | | |
206 | 211 | | |
| |||
210 | 215 | | |
211 | 216 | | |
212 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
213 | 250 | | |
214 | 251 | | |
215 | 252 | | |
| |||
Lines changed: 10 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
216 | 217 | | |
217 | 218 | | |
218 | 219 | | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
219 | 224 | | |
220 | 225 | | |
221 | 226 | | |
222 | 227 | | |
223 | 228 | | |
224 | 229 | | |
225 | 230 | | |
| 231 | + | |
226 | 232 | | |
227 | 233 | | |
228 | 234 | | |
| |||
350 | 356 | | |
351 | 357 | | |
352 | 358 | | |
| 359 | + | |
353 | 360 | | |
354 | 361 | | |
355 | 362 | | |
| |||
943 | 950 | | |
944 | 951 | | |
945 | 952 | | |
| 953 | + | |
946 | 954 | | |
947 | 955 | | |
948 | 956 | | |
| |||
965 | 973 | | |
966 | 974 | | |
967 | 975 | | |
| 976 | + | |
| 977 | + | |
968 | 978 | | |
969 | 979 | | |
970 | 980 | | |
| |||
0 commit comments