From ddb8cd402aff730f33fae458343cdb1e35e6abeb Mon Sep 17 00:00:00 2001 From: Rajarshee Chatterjee Date: Sun, 29 Jan 2023 15:14:00 +0530 Subject: [PATCH] refactor: Use Batch Queries --- src/database/queries/ChapterQueries.ts | 93 +++++++++++++++---------- src/database/queries/DownloadQueries.ts | 9 +-- src/redux/novel/novel.actions.js | 55 ++------------- src/redux/novel/novel.reducer.js | 8 +++ src/redux/novel/novel.types.js | 2 + 5 files changed, 79 insertions(+), 88 deletions(-) diff --git a/src/database/queries/ChapterQueries.ts b/src/database/queries/ChapterQueries.ts index 8ed85f7d..53d32e45 100644 --- a/src/database/queries/ChapterQueries.ts +++ b/src/database/queries/ChapterQueries.ts @@ -9,43 +9,35 @@ import { txnErrorCallback } from '@database/utils/helpers'; const db = SQLite.openDatabase('lnreader.db'); -const insertChaptersQuery = - 'INSERT INTO chapters (chapterUrl, chapterName, releaseDate, novelId) values (?, ?, ?, ?)'; +let insertChaptersQuery = ` +INSERT INTO chapters ( + chapterUrl, chapterName, releaseDate, + novelId +) +VALUES +`; export const insertChapters = async ( novelId: number, chapters: ChapterItem[], ) => { - db.transaction( - tx => { - chapters.map(chapter => - tx.executeSql( - insertChaptersQuery, - [ - chapter.chapterUrl, - chapter.chapterName, - chapter.releaseDate, - novelId, - ], - (_txObj, _res) => {}, - (_txObj, _error) => false, - // console.log( - // "Error ", - // error, - // " Chapter URL: ", - // chapter.chapterUrl, - // " Novel ID ", - // novelId - // ) - ), - ); - }, - _err => { - // console.log('Error', err); - }, - () => { - // console.log('Success ') - }, + const valuesArr: string[] = []; + + chapters?.forEach(chapter => { + valuesArr.push( + `( + "${chapter.chapterUrl}", + "${chapter.chapterName}", + "${chapter.releaseDate || ''}", + ${novelId} + )`, + ); + }); + + insertChaptersQuery += valuesArr.toString() + ';'; + + db.transaction(tx => + tx.executeSql(insertChaptersQuery, undefined, undefined, txnErrorCallback), ); }; @@ -62,10 +54,7 @@ export const getChapters = (novelId: number, sort: string, filter: string) => { const _array = (rows as any)._array; resolve(_array); }, - (_txObj, _error) => { - // console.log('Error ', error) - return false; - }, + txnErrorCallback, ); }), ); @@ -418,6 +407,38 @@ export const deleteChapter = async ( }); }; +export const deleteChapters = async ( + sourceId: number, + chapters?: ChapterItem[], +) => { + if (!chapters?.length) { + return; + } + + const chapterIdsString = chapters + ?.map(chapter => chapter.chapterId) + .toString(); + + const updateIsDownloadedQuery = `UPDATE chapters SET downloaded = 0 WHERE chapterId IN (${chapterIdsString})`; + const deleteChapterQuery = `DELETE FROM downloads WHERE downloadChapterId = (${chapterIdsString})`; + + await Promise.all( + chapters?.map(chapter => + deleteDownloadedImages(sourceId, chapter.novelId, chapter.chapterId), + ), + ); + + db.transaction(tx => { + tx.executeSql( + updateIsDownloadedQuery, + undefined, + undefined, + txnErrorCallback, + ); + tx.executeSql(deleteChapterQuery, undefined, undefined, txnErrorCallback); + }); +}; + const getLastReadChapterQuery = ` SELECT chapters.* FROM history diff --git a/src/database/queries/DownloadQueries.ts b/src/database/queries/DownloadQueries.ts index 17136924..772c5c2d 100644 --- a/src/database/queries/DownloadQueries.ts +++ b/src/database/queries/DownloadQueries.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ +import { txnErrorCallback } from '@database/utils/helpers'; import * as SQLite from 'expo-sqlite'; import { showToast } from '../../hooks/showToast'; import { sourceManager } from '../../sources/sourceManager'; @@ -36,7 +37,7 @@ export const fetchAndInsertChapterInDb = async ( downloadChapterQuery, [chapterId, chapter.chapterName, chapter.chapterText], (txObj, res) => {}, - (_txObj, error) => showToast(error), + txnErrorCallback, ); }); }; @@ -55,7 +56,7 @@ export const deleteChapterFromDb = (chapterId: number) => { deleteChapterFromDbQuery, [chapterId], (txObj, res) => {}, - (_txObj, error) => showToast(error.message), + txnErrorCallback, ); }); }; @@ -122,13 +123,13 @@ export const deleteReadChaptersFromDb = (chapterId: number) => { updateChaptersDeletedQuery, [], (txObj, res) => {}, - (txObj, error) => showToast(error.message), + txnErrorCallback, ); tx.executeSql( deleteReadChaptersFromDbQuery, [], (txObj, res) => showToast('Deleted read chapters.'), - (txObj, error) => showToast(error.message), + txnErrorCallback, ); }); }; diff --git a/src/redux/novel/novel.actions.js b/src/redux/novel/novel.actions.js index b9bdc6c7..d757616b 100644 --- a/src/redux/novel/novel.actions.js +++ b/src/redux/novel/novel.actions.js @@ -15,6 +15,7 @@ import { BOOKMARK_CHAPTER, MARK_PREVIOUS_CHAPTERS_READ, MARK_PREVIOUS_CHAPTERS_UNREAD, + ALL_CHAPTER_DELETED, } from './novel.types'; import { fetchNovel } from '../../services/Source/source'; @@ -34,6 +35,7 @@ import { markPreviuschaptersRead, markPreviousChaptersUnread, getNextChapter, + deleteChapters, } from '../../database/queries/ChapterQueries'; import { deleteUpdateFromDb } from '../../database/queries/UpdateQueries'; import { @@ -441,57 +443,14 @@ export const deleteChapterAction = */ export const deleteAllChaptersAction = (sourceId, chapters) => async dispatch => { - await new Promise((res, rej) => { - (async () => { - const downloaded = chapters.filter(f => !!f.downloaded); - if (downloaded.length === 0) { - res(); - } + const chapterIds = chapters.map(chapter => chapter.chapterId); + await deleteChapters(sourceId, chapters); - const coccurent = 5; - /** - * @type {Promise[][]} - */ - const removeBatches = []; - for (let i = 0; i < downloaded.length; i++) { - if (i % coccurent === 0) { - removeBatches.push([]); - } - removeBatches[removeBatches.length - 1].push( - new Promise(resolveRemoval => { - (async () => { - const chapter = downloaded[i]; - await deleteChapter( - sourceId, - chapter.novelId, - chapter.chapterId, - ); - - dispatch({ - type: CHAPTER_DELETED, - payload: chapter.chapterId, - }); - resolveRemoval(); - })(); - }), - ); - } - for (const rb of removeBatches) { - await Promise.all(rb); - } - res(); - })(); + dispatch({ + type: ALL_CHAPTER_DELETED, + payload: chapterIds, }); - // await Promise.all( - // chapters.map(async chapter => { - // await deleteChapter(sourceId, chapter.novelId, chapter.chapterId); - // dispatch({ - // type: CHAPTER_DELETED, - // payload: chapter.chapterId, - // }); - // }), - // ); showToast('Chapters deleted'); }; diff --git a/src/redux/novel/novel.reducer.js b/src/redux/novel/novel.reducer.js index 437237d0..d45c8b57 100644 --- a/src/redux/novel/novel.reducer.js +++ b/src/redux/novel/novel.reducer.js @@ -117,6 +117,14 @@ const novelReducer = (state = initialState, action) => { : chapter, ), }; + case CHAPTER_DELETED: + return { + ...state, + chapters: state.chapters.map(chapter => ({ + ...chapter, + downloaded: 0, + })), + }; case UPDATE_LAST_READ: return { ...state, diff --git a/src/redux/novel/novel.types.js b/src/redux/novel/novel.types.js index db901f62..858d6195 100644 --- a/src/redux/novel/novel.types.js +++ b/src/redux/novel/novel.types.js @@ -10,6 +10,8 @@ export const UPDATE_LAST_READ = 'UPDATE_LAST_READ'; export const CHAPTER_DOWNLOADED = 'CHAPTER_DOWNLOADED'; export const CHAPTER_DELETED = 'CHAPTER_DELETED'; +export const ALL_CHAPTER_DELETED = 'ALL_CHAPTER_DELETED'; + export const CHAPTER_DOWNLOADING = 'CHAPTER_DOWNLOADING'; export const CHAPTER_READ = 'CHAPTER_READ'; export const CHAPTER_UNREAD = 'CHAPTER_UNREAD';