@nozbe/watermelondb
Version:
Build powerful React Native and React web apps that scale from hundreds to tens of thousands of records and remain fast
73 lines (60 loc) • 2.15 kB
JavaScript
// @flow
import { Observable, switchMap, distinctUntilChanged, throttleTime } from '../../utils/rx'
import { logError } from '../../utils/common'
import { toPromise } from '../../utils/fp/Result'
import { type Unsubscribe } from '../../utils/subscriptions'
import type Query from '../../Query'
import type Model from '../../Model'
let isThrottlingDisabled = false
export function experimentalDisableObserveCountThrottling(): void {
isThrottlingDisabled = true
}
// Produces an observable version of a query count by re-querying the database
// when any change occurs in any of the relevant Stores.
//
// TODO: Potential optimizations:
// - increment/decrement counter using matchers on insert/delete
function observeCountThrottled<Record: Model>(query: Query<Record>): Observable<number> {
const { collection } = query
return collection.database.withChangesForTables(query.allTables).pipe(
throttleTime(250), // Note: this has a bug, but we'll delete it anyway
switchMap(() => toPromise((callback) => collection._fetchCount(query, callback))),
distinctUntilChanged(),
)
}
export default function subscribeToCount<Record: Model>(
query: Query<Record>,
isThrottled: boolean,
subscriber: (number) => void,
): Unsubscribe {
if (isThrottled && !isThrottlingDisabled) {
const observable = observeCountThrottled(query)
const subscription = observable.subscribe(subscriber)
return () => subscription.unsubscribe()
}
const { collection } = query
let unsubscribed = false
let previousCount = -1
const observeCountFetch = () => {
collection._fetchCount(query, (result) => {
if (result.error) {
logError(result.error.toString())
return
}
const count = result.value
const shouldEmit = count !== previousCount && !unsubscribed
previousCount = count
shouldEmit && subscriber(count)
})
}
const unsubscribe = collection.database.experimentalSubscribe(
query.allTables,
observeCountFetch,
{ name: 'subscribeToCount', query, subscriber },
)
observeCountFetch()
return () => {
unsubscribed = true
unsubscribe()
}
}