refactor: hydrate service interface
Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
020ea017eb
commit
a66a415ad3
|
|
@ -55,7 +55,7 @@
|
|||
"severity": "off"
|
||||
}
|
||||
],
|
||||
"cSpell.words": ["rsshub", "Русский"],
|
||||
"cSpell.words": ["Hydable", "rsshub", "Русский"],
|
||||
"editor.foldingImportsByDefault": true,
|
||||
"commentTranslate.hover.enabled": false,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
|
|
|
|||
|
|
@ -3,22 +3,10 @@ import { initializeDefaultIntegrationSettings } from "~/atoms/settings/integrati
|
|||
import { initializeDefaultUISettings } from "~/atoms/settings/ui"
|
||||
import { appLog } from "~/lib/log"
|
||||
import { sleep } from "~/lib/utils"
|
||||
import {
|
||||
EntryRelatedKey,
|
||||
EntryRelatedService,
|
||||
EntryService,
|
||||
FeedService,
|
||||
FeedUnreadService,
|
||||
SubscriptionService,
|
||||
} from "~/services"
|
||||
import { EntryService, FeedService, FeedUnreadService, SubscriptionService } from "~/services"
|
||||
import { InboxService } from "~/services/inbox"
|
||||
import type { Hydable } from "~/services/interface"
|
||||
import { ListService } from "~/services/list"
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
import { listActions } from "~/store/list"
|
||||
|
||||
import { entryActions, useEntryStore } from "../store/entry/store"
|
||||
import { feedActions, useFeedStore } from "../store/feed"
|
||||
import { subscriptionActions } from "../store/subscription"
|
||||
import { feedUnreadActions } from "../store/unread"
|
||||
|
||||
export const setHydrated = (v: boolean) => {
|
||||
window.__dbIsReady = v
|
||||
|
|
@ -27,13 +15,16 @@ export const setHydrated = (v: boolean) => {
|
|||
export const hydrateDatabaseToStore = async () => {
|
||||
async function hydrate() {
|
||||
const now = Date.now()
|
||||
await Promise.all([
|
||||
hydrateFeed(),
|
||||
hydrateSubscription(),
|
||||
hydrateFeedUnread(),
|
||||
hydrateEntry(),
|
||||
hydrateList(),
|
||||
])
|
||||
|
||||
const hydrates: Hydable[] = [
|
||||
FeedService,
|
||||
SubscriptionService,
|
||||
FeedUnreadService,
|
||||
EntryService,
|
||||
ListService,
|
||||
InboxService,
|
||||
]
|
||||
await Promise.all(hydrates.map((h) => h.hydrate()))
|
||||
|
||||
window.__dbIsReady = true
|
||||
const costTime = Date.now() - now
|
||||
|
|
@ -48,65 +39,6 @@ export const hydrateDatabaseToStore = async () => {
|
|||
})
|
||||
}
|
||||
|
||||
async function hydrateFeed() {
|
||||
const feeds = await FeedService.findAll()
|
||||
feedActions.upsertMany(feeds)
|
||||
return useFeedStore.getState().feeds
|
||||
}
|
||||
|
||||
async function hydrateFeedUnread() {
|
||||
const unread = await FeedUnreadService.getAll()
|
||||
|
||||
return feedUnreadActions.hydrate(unread)
|
||||
}
|
||||
async function hydrateEntry() {
|
||||
const [entries, entryRelated, feedEntries, collections] = await Promise.all([
|
||||
EntryService.findAll(),
|
||||
|
||||
EntryRelatedService.findAll(EntryRelatedKey.READ),
|
||||
EntryRelatedService.findAll(EntryRelatedKey.FEED_ID),
|
||||
EntryRelatedService.findAll(EntryRelatedKey.COLLECTION),
|
||||
])
|
||||
|
||||
const storeValue = [] as FlatEntryModel[]
|
||||
for (const entry of entries) {
|
||||
const entryRelatedFeedId = entry.feedId || feedEntries[entry.id]
|
||||
if (!entryRelatedFeedId) {
|
||||
logHydrateError(`Entry ${entry.id} has no related feed id`)
|
||||
continue
|
||||
}
|
||||
|
||||
storeValue.push({
|
||||
entries: entry,
|
||||
feedId: entryRelatedFeedId,
|
||||
read: entryRelated[entry.id] || false,
|
||||
collections: collections[entry.id] as {
|
||||
createdAt: string
|
||||
},
|
||||
})
|
||||
}
|
||||
entryActions.hydrate(storeValue)
|
||||
useEntryStore.setState({
|
||||
starIds: new Set(Object.keys(collections)),
|
||||
})
|
||||
}
|
||||
|
||||
async function hydrateSubscription() {
|
||||
const subscriptions = await SubscriptionService.findAll()
|
||||
|
||||
subscriptionActions.upsertMany(subscriptions)
|
||||
}
|
||||
|
||||
async function hydrateList() {
|
||||
const lists = await ListService.findAll()
|
||||
listActions.upsertMany(lists)
|
||||
}
|
||||
|
||||
const logHydrateError = (message: string) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug(`Hydrate error: ${message}, maybe local database data is dirty.`)
|
||||
}
|
||||
|
||||
export const hydrateSettings = () => {
|
||||
initializeDefaultUISettings()
|
||||
initializeDefaultGeneralSettings()
|
||||
|
|
|
|||
|
|
@ -80,5 +80,9 @@ class CleanerServiceStatic {
|
|||
cleanerModel.bulkDelete(data.map((d) => d.refId)),
|
||||
])
|
||||
}
|
||||
|
||||
async cleanRefById(refIds: string[]) {
|
||||
return cleanerModel.bulkDelete(refIds)
|
||||
}
|
||||
}
|
||||
export const CleanerService = new CleanerServiceStatic()
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
import { browserDB } from "~/database"
|
||||
import { appLog } from "~/lib/log"
|
||||
import type { EntryModel } from "~/models/types"
|
||||
import type { FlatEntryModel } from "~/store/entry"
|
||||
import { entryActions, useEntryStore } from "~/store/entry"
|
||||
|
||||
import { BaseService } from "./base"
|
||||
import { CleanerService } from "./cleaner"
|
||||
import { EntryRelatedKey, EntryRelatedService } from "./entry-related"
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
type EntryCollection = {
|
||||
createdAt: string
|
||||
}
|
||||
class EntryServiceStatic extends BaseService<EntryModel> {
|
||||
class EntryServiceStatic extends BaseService<EntryModel> implements Hydable {
|
||||
constructor() {
|
||||
super(browserDB.entries)
|
||||
}
|
||||
|
|
@ -77,6 +81,7 @@ class EntryServiceStatic extends BaseService<EntryModel> {
|
|||
this.table.bulkDelete(entryIds),
|
||||
EntryRelatedService.deleteItems(EntryRelatedKey.READ, entryIds),
|
||||
EntryRelatedService.deleteItems(EntryRelatedKey.COLLECTION, entryIds),
|
||||
CleanerService.cleanRefById(entryIds),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +93,48 @@ class EntryServiceStatic extends BaseService<EntryModel> {
|
|||
EntryRelatedService.deleteItems(EntryRelatedKey.COLLECTION, deleteEntryIds),
|
||||
])
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const [entries, entryRelated, feedEntries, collections] = await Promise.all([
|
||||
EntryService.findAll(),
|
||||
|
||||
EntryRelatedService.findAll(EntryRelatedKey.READ),
|
||||
EntryRelatedService.findAll(EntryRelatedKey.FEED_ID),
|
||||
EntryRelatedService.findAll(EntryRelatedKey.COLLECTION),
|
||||
])
|
||||
|
||||
const storeValue = [] as FlatEntryModel[]
|
||||
const dirtyEntryIds = [] as string[]
|
||||
for (const entry of entries) {
|
||||
const entryRelatedFeedId = entry.feedId || feedEntries[entry.id]
|
||||
if (!entryRelatedFeedId) {
|
||||
appLog(`[Data hydrate warning]: Entry ${entry.id} has no related feed id`)
|
||||
dirtyEntryIds.push(entry.id)
|
||||
continue
|
||||
}
|
||||
|
||||
storeValue.push({
|
||||
entries: entry,
|
||||
feedId: entryRelatedFeedId,
|
||||
read: entryRelated[entry.id] || false,
|
||||
collections: collections[entry.id] as {
|
||||
createdAt: string
|
||||
},
|
||||
})
|
||||
}
|
||||
entryActions.hydrate(storeValue)
|
||||
useEntryStore.setState({
|
||||
starIds: new Set(Object.keys(collections)),
|
||||
})
|
||||
|
||||
if (dirtyEntryIds.length > 0) {
|
||||
// Remove entries that have no related feed id
|
||||
EntryService.deleteEntries(dirtyEntryIds)
|
||||
appLog(
|
||||
`[Data hydrate warning]: Entry ${dirtyEntryIds.join(", ")} has no related feed id, cleanup..`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const EntryService = new EntryServiceStatic()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { browserDB } from "~/database"
|
||||
import { feedUnreadActions } from "~/store/unread"
|
||||
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
const feedUnreadModel = browserDB.feedUnreads
|
||||
class ServiceStatic {
|
||||
class ServiceStatic implements Hydable {
|
||||
updateFeedUnread(list: [string, number][]) {
|
||||
return feedUnreadModel.bulkPut(list.map(([feedId, count]) => ({ id: feedId, count })))
|
||||
}
|
||||
|
|
@ -22,6 +25,12 @@ class ServiceStatic {
|
|||
async bulkDelete(ids: string[]) {
|
||||
return feedUnreadModel.bulkDelete(ids)
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const unread = await FeedUnreadService.getAll()
|
||||
|
||||
return feedUnreadActions.hydrate(unread)
|
||||
}
|
||||
}
|
||||
|
||||
export const FeedUnreadService = new ServiceStatic()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { browserDB } from "~/database"
|
||||
import type { FeedModel, FeedOrListModel } from "~/models/types"
|
||||
import { feedActions } from "~/store/feed"
|
||||
|
||||
import { BaseService } from "./base"
|
||||
import { CleanerService } from "./cleaner"
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
type FeedModelWithId = FeedModel & { id: string }
|
||||
class ServiceStatic extends BaseService<FeedModelWithId> {
|
||||
class ServiceStatic extends BaseService<FeedModelWithId> implements Hydable {
|
||||
constructor() {
|
||||
super(browserDB.feeds)
|
||||
}
|
||||
|
|
@ -27,6 +29,11 @@ class ServiceStatic extends BaseService<FeedModelWithId> {
|
|||
async bulkDelete(ids: string[]) {
|
||||
return this.table.bulkDelete(ids)
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const feeds = await FeedService.findAll()
|
||||
feedActions.upsertMany(feeds)
|
||||
}
|
||||
}
|
||||
|
||||
export const FeedService = new ServiceStatic()
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { browserDB } from "~/database"
|
||||
import type { InboxModel } from "~/models/types"
|
||||
import { inboxActions } from "~/store/inbox"
|
||||
|
||||
import { BaseService } from "./base"
|
||||
import { CleanerService } from "./cleaner"
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
class ServiceStatic extends BaseService<{ id: string }> {
|
||||
class ServiceStatic extends BaseService<{ id: string }> implements Hydable {
|
||||
constructor() {
|
||||
super(browserDB.inboxes)
|
||||
}
|
||||
|
|
@ -28,6 +30,11 @@ class ServiceStatic extends BaseService<{ id: string }> {
|
|||
async bulkDelete(ids: string[]) {
|
||||
return this.table.bulkDelete(ids)
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const data = await this.findAll()
|
||||
inboxActions.upsertMany(data)
|
||||
}
|
||||
}
|
||||
|
||||
export const InboxService = new ServiceStatic()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export interface Hydable {
|
||||
hydrate: () => Promise<void>
|
||||
}
|
||||
|
|
@ -2,11 +2,13 @@ import { omit } from "lodash-es"
|
|||
|
||||
import { browserDB } from "~/database"
|
||||
import type { ListModel } from "~/models/types"
|
||||
import { listActions } from "~/store/list"
|
||||
|
||||
import { BaseService } from "./base"
|
||||
import { CleanerService } from "./cleaner"
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
class ServiceStatic extends BaseService<{ id: string }> {
|
||||
class ServiceStatic extends BaseService<{ id: string }> implements Hydable {
|
||||
constructor() {
|
||||
super(browserDB.lists)
|
||||
}
|
||||
|
|
@ -32,6 +34,11 @@ class ServiceStatic extends BaseService<{ id: string }> {
|
|||
async bulkDelete(ids: string[]) {
|
||||
return this.table.bulkDelete(ids)
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const lists = await ListService.findAll()
|
||||
listActions.upsertMany(lists)
|
||||
}
|
||||
}
|
||||
|
||||
export const ListService = new ServiceStatic()
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ import { uniq } from "lodash-es"
|
|||
|
||||
import { browserDB } from "~/database"
|
||||
import type { SubscriptionFlatModel } from "~/store/subscription"
|
||||
import { subscriptionActions } from "~/store/subscription"
|
||||
|
||||
import { BaseService } from "./base"
|
||||
import type { Hydable } from "./interface"
|
||||
|
||||
type SubscriptionModelWithId = SubscriptionFlatModel & { id: string }
|
||||
|
||||
class SubscriptionServiceStatic extends BaseService<SubscriptionModelWithId> {
|
||||
class SubscriptionServiceStatic extends BaseService<SubscriptionModelWithId> implements Hydable {
|
||||
constructor() {
|
||||
super(browserDB.subscriptions)
|
||||
}
|
||||
|
|
@ -68,6 +70,12 @@ class SubscriptionServiceStatic extends BaseService<SubscriptionModelWithId> {
|
|||
.and((item) => feedIdList.includes(item.feedId))
|
||||
.modify({ category })
|
||||
}
|
||||
|
||||
async hydrate() {
|
||||
const subscriptions = await SubscriptionService.findAll()
|
||||
|
||||
subscriptionActions.upsertMany(subscriptions)
|
||||
}
|
||||
}
|
||||
|
||||
export const SubscriptionService = new SubscriptionServiceStatic()
|
||||
|
|
|
|||
Loading…
Reference in New Issue