Skip to content

Commit 0796248

Browse files
authored
SF-3670 Fix slowdown in the Biblical Terms tab (#3616)
1 parent b4c0ae8 commit 0796248

File tree

5 files changed

+56
-22
lines changed

5 files changed

+56
-22
lines changed

src/RealtimeServer/scriptureforge/models/biblical-term.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
import { PROJECT_DATA_INDEX_PATHS, ProjectData } from '../../common/models/project-data';
2+
import { obj } from '../../common/utils/obj-path';
23
import { BiblicalTermDefinition } from './biblical-term-definition';
34

45
export const BIBLICAL_TERM_COLLECTION = 'biblical_terms';
5-
export const BIBLICAL_TERM_INDEX_PATHS = PROJECT_DATA_INDEX_PATHS;
6+
export const BIBLICAL_TERM_INDEX_PATHS = [
7+
...PROJECT_DATA_INDEX_PATHS,
8+
// Index for SFProjectService.queryBiblicalTerms()
9+
{
10+
[obj<BiblicalTerm>().pathStr(n => n.projectRef)]: 1,
11+
[obj<BiblicalTerm>().pathStr(n => n.references)]: 1
12+
}
13+
];
614

715
export function getBiblicalTermDocId(projectId: string, dataId: string): string {
816
return `${projectId}:${dataId}`;

src/SIL.XForge.Scripture/ClientApp/src/app/core/sf-project.service.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { DestroyRef, Injectable } from '@angular/core';
2+
import { VerseRef } from '@sillsdev/scripture';
23
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
34
import { obj } from 'realtime-server/lib/esm/common/utils/obj-path';
45
import { AudioTiming } from 'realtime-server/lib/esm/scriptureforge/models/audio-timing';
@@ -178,9 +179,21 @@ export class SFProjectService extends ProjectService<SFProject, SFProjectDoc> {
178179
return this.realtimeService.subscribeQuery(TextAudioDoc.COLLECTION, queryParams, destroyRef);
179180
}
180181

181-
queryBiblicalTerms(sfProjectId: string, destroyRef: DestroyRef): Promise<RealtimeQuery<BiblicalTermDoc>> {
182+
queryBiblicalTerms(
183+
sfProjectId: string,
184+
bookNum: number,
185+
destroyRef: DestroyRef
186+
): Promise<RealtimeQuery<BiblicalTermDoc>> {
187+
const bookStart = VerseRef.getBBBCCCVVV(bookNum, 0, 0);
188+
const bookEnd = VerseRef.getBBBCCCVVV(bookNum + 1, 0, 0);
182189
const queryParams: QueryParameters = {
183-
[obj<BiblicalTerm>().pathStr(t => t.projectRef)]: sfProjectId
190+
[obj<BiblicalTerm>().pathStr(t => t.projectRef)]: sfProjectId,
191+
[obj<BiblicalTerm>().pathStr(q => q.references)]: {
192+
$elemMatch: {
193+
$gte: bookStart,
194+
$lt: bookEnd
195+
}
196+
}
184197
};
185198
return this.realtimeService.subscribeQuery(BiblicalTermDoc.COLLECTION, queryParams, destroyRef);
186199
}

src/SIL.XForge.Scripture/ClientApp/src/app/translate/biblical-terms/biblical-terms.component.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ describe('BiblicalTermsComponent', () => {
437437
env.setupProjectData('en');
438438
env.onlineStatus = false;
439439
env.wait();
440+
env.component.biblicalTermsLoaded = false;
441+
env.wait();
440442
expect(env.offlineMessage.length).toBe(1);
441443
}));
442444

@@ -483,7 +485,7 @@ class TestEnvironment {
483485

484486
constructor(projectId: string | undefined, bookNum: number, chapter: number, verse: string = '0') {
485487
when(mockedI18nService.locale$).thenReturn(this.locale$);
486-
when(mockedProjectService.queryBiblicalTerms(anything(), anything())).thenCall(sfProjectId => {
488+
when(mockedProjectService.queryBiblicalTerms(anything(), anything(), anything())).thenCall(sfProjectId => {
487489
const parameters: QueryParameters = {
488490
[obj<BiblicalTerm>().pathStr(t => t.projectRef)]: sfProjectId
489491
};

src/SIL.XForge.Scripture/ClientApp/src/app/translate/biblical-terms/biblical-terms.component.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ import {
3737
} from 'realtime-server/lib/esm/scriptureforge/models/note-thread';
3838
import { SF_PROJECT_RIGHTS, SFProjectDomain } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-rights';
3939
import { fromVerseRef } from 'realtime-server/lib/esm/scriptureforge/models/verse-ref-data';
40-
import { BehaviorSubject, combineLatest, firstValueFrom, merge, Observable, Subscription } from 'rxjs';
41-
import { filter } from 'rxjs/operators';
40+
import { BehaviorSubject, combineLatest, defer, firstValueFrom, from, merge, Observable, Subscription } from 'rxjs';
41+
import { filter, switchMap } from 'rxjs/operators';
4242
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
4343
import { DialogService } from 'xforge-common/dialog.service';
4444
import { I18nService } from 'xforge-common/i18n.service';
@@ -354,7 +354,11 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
354354
// Subscribe to any project, book, chapter, verse, locale, biblical term, or note changes
355355
this.loadingStarted();
356356
this.categoriesLoading = true;
357-
const biblicalTermsAndNotesChanges$: Observable<any> = await this.getBiblicalTermsAndNotesChanges(projectId);
357+
const biblicalTermsNotesChanges$: Observable<any> = await this.getBiblicalTermsNotesChanges(projectId);
358+
const biblicalTermsChanges$: Observable<any> = this.bookNum$.pipe(
359+
filter(bookNum => bookNum !== 0),
360+
switchMap(bookNum => this.getBiblicalTermsChanges(projectId, bookNum))
361+
);
358362

359363
this.biblicalTermSub?.unsubscribe();
360364

@@ -363,18 +367,21 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
363367
this.chapter$,
364368
this.verse$,
365369
this.i18n.locale$,
366-
biblicalTermsAndNotesChanges$
370+
biblicalTermsChanges$,
371+
biblicalTermsNotesChanges$
367372
])
368373
.pipe(
369374
filter(([bookNum, chapter, verse]) => bookNum !== 0 && chapter !== 0 && verse !== null),
370375
quietTakeUntilDestroyed(this.destroyRef)
371376
)
372377
.subscribe(([bookNum, chapter, verse]) => {
373378
this.filterBiblicalTerms(bookNum, chapter, verse);
379+
this.biblicalTermsLoaded = true;
374380
this.categoriesLoading = false;
381+
this.loadingFinished();
375382
});
376383

377-
if (!this.appOnline && biblicalTermsAndNotesChanges$.pipe(filter(val => val == null))) {
384+
if (!this.appOnline && !this.biblicalTermsLoaded) {
378385
this.loadingFinished();
379386
} else {
380387
this.biblicalTermsLoaded = true;
@@ -533,23 +540,27 @@ export class BiblicalTermsComponent extends DataLoadingComponent implements OnDe
533540
this.loadingFinished();
534541
}
535542

536-
private async getBiblicalTermsAndNotesChanges(sfProjectId: string): Promise<Observable<any>> {
537-
// Clean up existing queries
538-
this.biblicalTermQuery?.dispose();
543+
private getBiblicalTermsChanges(sfProjectId: string, bookNum: number): Observable<any> {
544+
return defer(() => {
545+
this.biblicalTermQuery?.dispose();
546+
return from(this.projectService.queryBiblicalTerms(sfProjectId, bookNum, this.destroyRef)).pipe(
547+
switchMap(query => {
548+
this.biblicalTermQuery = query;
549+
return merge(query.ready$.pipe(filter(isReady => isReady)), query.remoteChanges$, query.remoteDocChanges$);
550+
})
551+
);
552+
});
553+
}
554+
555+
private async getBiblicalTermsNotesChanges(sfProjectId: string): Promise<Observable<any>> {
556+
// Clean up existing query
539557
this.noteThreadQuery?.dispose();
540558

541-
// Get the Biblical Terms and Notes
542-
[this.biblicalTermQuery, this.noteThreadQuery] = await Promise.all([
543-
this.projectService.queryBiblicalTerms(sfProjectId, this.destroyRef),
544-
this.projectService.queryBiblicalTermNoteThreads(sfProjectId, this.destroyRef)
545-
]);
559+
// Get the Biblical Terms Notes
560+
this.noteThreadQuery = await this.projectService.queryBiblicalTermNoteThreads(sfProjectId, this.destroyRef);
546561

547562
// Return a merged observable to monitor changes
548-
549563
return merge(
550-
this.biblicalTermQuery.ready$.pipe(filter(isReady => isReady)),
551-
this.biblicalTermQuery.remoteChanges$,
552-
this.biblicalTermQuery.remoteDocChanges$,
553564
this.noteThreadQuery.localChanges$,
554565
this.noteThreadQuery.ready$.pipe(filter(isReady => isReady)),
555566
this.noteThreadQuery.remoteChanges$,

src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/editor.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4921,7 +4921,7 @@ class TestEnvironment {
49214921
noopDestroyRef
49224922
)
49234923
);
4924-
when(mockedSFProjectService.queryBiblicalTerms(anything(), anything())).thenCall(id =>
4924+
when(mockedSFProjectService.queryBiblicalTerms(anything(), anything(), anything())).thenCall(id =>
49254925
this.realtimeService.subscribeQuery(
49264926
BiblicalTermDoc.COLLECTION,
49274927
{

0 commit comments

Comments
 (0)