mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-25 18:47:51 +02:00
feat: db changes to accommodate new cross device syncing logic. (#450)
* feat: db changes to accommodate new syncing logic. Using timestamp to sync is a bit skewed due to system clock etc and therefore there was a lot of issues with it such as removing a manga that shouldn't have been removed. Marking chapters as unread even though it was marked as a read. Hopefully by using versioning system it should eliminate those issues. * chore: add new line. * chore: remove isSyncing from Chapter/Manga model. * chore: remove isSyncing leftover. * chore: remove isSyncing. * refactor: remove isSync guard. Just use it directly to 1 now since we don't have the isSyncing field in Manga or Chapter. * Lint and stuff * Add missing , --------- Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
@ -29,6 +29,7 @@ class ChapterRepositoryImpl(
|
||||
chapter.sourceOrder,
|
||||
chapter.dateFetch,
|
||||
chapter.dateUpload,
|
||||
chapter.version,
|
||||
)
|
||||
val lastInsertId = chaptersQueries.selectLastInsertedRowId().executeAsOne()
|
||||
chapter.copy(id = lastInsertId)
|
||||
@ -64,6 +65,8 @@ class ChapterRepositoryImpl(
|
||||
dateFetch = chapterUpdate.dateFetch,
|
||||
dateUpload = chapterUpdate.dateUpload,
|
||||
chapterId = chapterUpdate.id,
|
||||
version = chapterUpdate.version,
|
||||
isSyncing = 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -124,6 +127,7 @@ class ChapterRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
private fun mapChapter(
|
||||
id: Long,
|
||||
mangaId: Long,
|
||||
@ -138,6 +142,9 @@ class ChapterRepositoryImpl(
|
||||
dateFetch: Long,
|
||||
dateUpload: Long,
|
||||
lastModifiedAt: Long,
|
||||
version: Long,
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
isSyncing: Long,
|
||||
): Chapter = Chapter(
|
||||
id = id,
|
||||
mangaId = mangaId,
|
||||
@ -152,5 +159,6 @@ class ChapterRepositoryImpl(
|
||||
chapterNumber = chapterNumber,
|
||||
scanlator = scanlator,
|
||||
lastModifiedAt = lastModifiedAt,
|
||||
version = version,
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
|
||||
object MangaMapper {
|
||||
@Suppress("LongParameterList")
|
||||
fun mapManga(
|
||||
id: Long,
|
||||
source: Long,
|
||||
@ -28,6 +29,9 @@ object MangaMapper {
|
||||
calculateInterval: Long,
|
||||
lastModifiedAt: Long,
|
||||
favoriteModifiedAt: Long?,
|
||||
version: Long,
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
isSyncing: Long,
|
||||
): Manga = Manga(
|
||||
id = id,
|
||||
source = source,
|
||||
@ -51,8 +55,10 @@ object MangaMapper {
|
||||
initialized = initialized,
|
||||
lastModifiedAt = lastModifiedAt,
|
||||
favoriteModifiedAt = favoriteModifiedAt,
|
||||
version = version,
|
||||
)
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
fun mapLibraryManga(
|
||||
id: Long,
|
||||
source: Long,
|
||||
@ -76,6 +82,8 @@ object MangaMapper {
|
||||
calculateInterval: Long,
|
||||
lastModifiedAt: Long,
|
||||
favoriteModifiedAt: Long?,
|
||||
version: Long,
|
||||
isSyncing: Long,
|
||||
totalCount: Long,
|
||||
readCount: Double,
|
||||
latestUpload: Long,
|
||||
@ -107,6 +115,8 @@ object MangaMapper {
|
||||
calculateInterval,
|
||||
lastModifiedAt,
|
||||
favoriteModifiedAt,
|
||||
version,
|
||||
isSyncing,
|
||||
),
|
||||
category = category,
|
||||
totalChapters = totalCount,
|
||||
|
@ -106,6 +106,7 @@ class MangaRepositoryImpl(
|
||||
coverLastModified = manga.coverLastModified,
|
||||
dateAdded = manga.dateAdded,
|
||||
updateStrategy = manga.updateStrategy,
|
||||
version = manga.version,
|
||||
)
|
||||
mangasQueries.selectLastInsertedRowId()
|
||||
}
|
||||
@ -155,6 +156,8 @@ class MangaRepositoryImpl(
|
||||
dateAdded = value.dateAdded,
|
||||
mangaId = value.id,
|
||||
updateStrategy = value.updateStrategy?.let(UpdateStrategyColumnAdapter::encode),
|
||||
version = value.version,
|
||||
isSyncing = 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ CREATE TABLE chapters(
|
||||
date_fetch INTEGER NOT NULL,
|
||||
date_upload INTEGER NOT NULL,
|
||||
last_modified_at INTEGER NOT NULL DEFAULT 0,
|
||||
version INTEGER NOT NULL DEFAULT 0,
|
||||
is_syncing INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
@ -30,6 +32,22 @@ BEGIN
|
||||
WHERE _id = new._id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER update_chapter_and_manga_version AFTER UPDATE ON chapters
|
||||
WHEN new.is_syncing = 0 AND (
|
||||
new.read != old.read OR
|
||||
new.bookmark != old.bookmark OR
|
||||
new.last_page_read != old.last_page_read
|
||||
)
|
||||
BEGIN
|
||||
-- Update the chapter version
|
||||
UPDATE chapters SET version = version + 1
|
||||
WHERE _id = new._id;
|
||||
|
||||
-- Update the manga version
|
||||
UPDATE mangas SET version = version + 1
|
||||
WHERE _id = new.manga_id AND (SELECT is_syncing FROM mangas WHERE _id = new.manga_id) = 0;
|
||||
END;
|
||||
|
||||
getChapterById:
|
||||
SELECT *
|
||||
FROM chapters
|
||||
@ -73,9 +91,14 @@ removeChaptersWithIds:
|
||||
DELETE FROM chapters
|
||||
WHERE _id IN :chapterIds;
|
||||
|
||||
resetIsSyncing:
|
||||
UPDATE chapters
|
||||
SET is_syncing = 0
|
||||
WHERE is_syncing = 1;
|
||||
|
||||
insert:
|
||||
INSERT INTO chapters(manga_id, url, name, scanlator, read, bookmark, last_page_read, chapter_number, source_order, date_fetch, date_upload, last_modified_at)
|
||||
VALUES (:mangaId, :url, :name, :scanlator, :read, :bookmark, :lastPageRead, :chapterNumber, :sourceOrder, :dateFetch, :dateUpload, 0);
|
||||
INSERT INTO chapters(manga_id, url, name, scanlator, read, bookmark, last_page_read, chapter_number, source_order, date_fetch, date_upload, last_modified_at, version, is_syncing)
|
||||
VALUES (:mangaId, :url, :name, :scanlator, :read, :bookmark, :lastPageRead, :chapterNumber, :sourceOrder, :dateFetch, :dateUpload, 0, :version, 0);
|
||||
|
||||
update:
|
||||
UPDATE chapters
|
||||
@ -89,7 +112,9 @@ SET manga_id = coalesce(:mangaId, manga_id),
|
||||
chapter_number = coalesce(:chapterNumber, chapter_number),
|
||||
source_order = coalesce(:sourceOrder, source_order),
|
||||
date_fetch = coalesce(:dateFetch, date_fetch),
|
||||
date_upload = coalesce(:dateUpload, date_upload)
|
||||
date_upload = coalesce(:dateUpload, date_upload),
|
||||
version = coalesce(:version, version),
|
||||
is_syncing = coalesce(:isSyncing, is_syncing)
|
||||
WHERE _id = :chapterId;
|
||||
|
||||
selectLastInsertedRowId:
|
||||
|
@ -25,7 +25,9 @@ CREATE TABLE mangas(
|
||||
update_strategy INTEGER AS UpdateStrategy NOT NULL DEFAULT 0,
|
||||
calculate_interval INTEGER DEFAULT 0 NOT NULL,
|
||||
last_modified_at INTEGER NOT NULL DEFAULT 0,
|
||||
favorite_modified_at INTEGER
|
||||
favorite_modified_at INTEGER,
|
||||
version INTEGER NOT NULL DEFAULT 0,
|
||||
is_syncing INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE INDEX library_favorite_index ON mangas(favorite) WHERE favorite = 1;
|
||||
@ -48,6 +50,16 @@ BEGIN
|
||||
WHERE _id = new._id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER update_manga_version AFTER UPDATE ON mangas
|
||||
BEGIN
|
||||
UPDATE mangas SET version = version + 1
|
||||
WHERE _id = new._id AND new.is_syncing = 0 AND (
|
||||
new.url != old.url OR
|
||||
new.description != old.description OR
|
||||
new.favorite != old.favorite
|
||||
);
|
||||
END;
|
||||
|
||||
getMangaById:
|
||||
SELECT *
|
||||
FROM mangas
|
||||
@ -104,6 +116,11 @@ resetViewerFlags:
|
||||
UPDATE mangas
|
||||
SET viewer = 0;
|
||||
|
||||
resetIsSyncing:
|
||||
UPDATE mangas
|
||||
SET is_syncing = 0
|
||||
WHERE is_syncing = 1;
|
||||
|
||||
getSourceIdsWithNonLibraryManga:
|
||||
SELECT source, COUNT(*) AS manga_count
|
||||
FROM mangas
|
||||
@ -116,8 +133,8 @@ WHERE favorite = 0
|
||||
AND source IN :sourceIds;
|
||||
|
||||
insert:
|
||||
INSERT INTO mangas(source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, calculate_interval, last_modified_at)
|
||||
VALUES (:source, :url, :artist, :author, :description, :genre, :title, :status, :thumbnailUrl, :favorite, :lastUpdate, :nextUpdate, :initialized, :viewerFlags, :chapterFlags, :coverLastModified, :dateAdded, :updateStrategy, :calculateInterval, 0);
|
||||
INSERT INTO mangas(source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, calculate_interval, last_modified_at, version)
|
||||
VALUES (:source, :url, :artist, :author, :description, :genre, :title, :status, :thumbnailUrl, :favorite, :lastUpdate, :nextUpdate, :initialized, :viewerFlags, :chapterFlags, :coverLastModified, :dateAdded, :updateStrategy, :calculateInterval, 0, :version);
|
||||
|
||||
update:
|
||||
UPDATE mangas SET
|
||||
@ -139,7 +156,9 @@ UPDATE mangas SET
|
||||
cover_last_modified = coalesce(:coverLastModified, cover_last_modified),
|
||||
date_added = coalesce(:dateAdded, date_added),
|
||||
update_strategy = coalesce(:updateStrategy, update_strategy),
|
||||
calculate_interval = coalesce(:calculateInterval, calculate_interval)
|
||||
calculate_interval = coalesce(:calculateInterval, calculate_interval),
|
||||
version = coalesce(:version, version),
|
||||
is_syncing = coalesce(:isSyncing, is_syncing)
|
||||
WHERE _id = :mangaId;
|
||||
|
||||
selectLastInsertedRowId:
|
||||
|
@ -2,25 +2,22 @@ CREATE TABLE mangas_categories(
|
||||
_id INTEGER NOT NULL PRIMARY KEY,
|
||||
manga_id INTEGER NOT NULL,
|
||||
category_id INTEGER NOT NULL,
|
||||
last_modified_at INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY(category_id) REFERENCES categories (_id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_last_modified_at_mangas_categories
|
||||
AFTER UPDATE ON mangas_categories
|
||||
FOR EACH ROW
|
||||
CREATE TRIGGER insert_manga_category_update_version AFTER INSERT ON mangas_categories
|
||||
BEGIN
|
||||
UPDATE mangas_categories
|
||||
SET last_modified_at = strftime('%s', 'now')
|
||||
WHERE _id = new._id;
|
||||
UPDATE mangas
|
||||
SET version = version + 1
|
||||
WHERE _id = new.manga_id AND (SELECT is_syncing FROM mangas WHERE _id = new.manga_id) = 0;
|
||||
END;
|
||||
|
||||
insert:
|
||||
INSERT INTO mangas_categories(manga_id, category_id, last_modified_at)
|
||||
VALUES (:mangaId, :categoryId, 0);
|
||||
INSERT INTO mangas_categories(manga_id, category_id)
|
||||
VALUES (:mangaId, :categoryId);
|
||||
|
||||
deleteMangaCategoryByMangaId:
|
||||
DELETE FROM mangas_categories
|
||||
|
46
data/src/main/sqldelight/tachiyomi/migrations/2.sqm
Normal file
46
data/src/main/sqldelight/tachiyomi/migrations/2.sqm
Normal file
@ -0,0 +1,46 @@
|
||||
-- Mangas table
|
||||
ALTER TABLE mangas ADD COLUMN version INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE mangas ADD COLUMN is_syncing INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
-- Chapters table
|
||||
ALTER TABLE chapters ADD COLUMN version INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE chapters ADD COLUMN is_syncing INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
-- Mangas triggers
|
||||
DROP TRIGGER IF EXISTS update_manga_version;
|
||||
CREATE TRIGGER update_manga_version AFTER UPDATE ON mangas
|
||||
BEGIN
|
||||
UPDATE mangas SET version = version + 1
|
||||
WHERE _id = new._id AND new.is_syncing = 0 AND (
|
||||
new.url != old.url OR
|
||||
new.description != old.description OR
|
||||
new.favorite != old.favorite
|
||||
);
|
||||
END;
|
||||
|
||||
-- Chapters triggers
|
||||
DROP TRIGGER IF EXISTS update_chapter_and_manga_version;
|
||||
CREATE TRIGGER update_chapter_and_manga_version AFTER UPDATE ON chapters
|
||||
WHEN new.is_syncing = 0 AND (
|
||||
new.read != old.read OR
|
||||
new.bookmark != old.bookmark OR
|
||||
new.last_page_read != old.last_page_read
|
||||
)
|
||||
BEGIN
|
||||
-- Update the chapter version
|
||||
UPDATE chapters SET version = version + 1
|
||||
WHERE _id = new._id;
|
||||
|
||||
-- Update the manga version
|
||||
UPDATE mangas SET version = version + 1
|
||||
WHERE _id = new.manga_id AND (SELECT is_syncing FROM mangas WHERE _id = new.manga_id) = 0;
|
||||
END;
|
||||
|
||||
-- manga_categories table
|
||||
DROP TRIGGER IF EXISTS insert_manga_category_update_version;
|
||||
CREATE TRIGGER insert_manga_category_update_version AFTER INSERT ON mangas_categories
|
||||
BEGIN
|
||||
UPDATE mangas
|
||||
SET version = version + 1
|
||||
WHERE _id = new.manga_id AND (SELECT is_syncing FROM mangas WHERE _id = new.manga_id) = 0;
|
||||
END;
|
Reference in New Issue
Block a user