Skip to content

Commit a17f2fc

Browse files
authored
perf: use hasMore instead of live count on merge suggestion lists (#4261)
Signed-off-by: Yeganathan S <63534555+skwowet@users.noreply.github.com>
1 parent 8a56c11 commit a17f2fc

8 files changed

Lines changed: 116 additions & 78 deletions

File tree

backend/src/database/repositories/memberRepository.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ class MemberRepository {
410410
return { count: await getTotalCount() }
411411
}
412412

413+
const pageLimit = args.limit
414+
const queryLimit = pageLimit + 1
415+
413416
const mems = await options.database.sequelize.query(
414417
`
415418
SELECT
@@ -452,7 +455,7 @@ class MemberRepository {
452455
{
453456
replacements: {
454457
segmentIds,
455-
limit: args.limit,
458+
limit: queryLimit,
456459
offset: args.offset,
457460
displayName: args?.filter?.displayName ? `${args.filter.displayName}%` : undefined,
458461
memberId: args?.filter?.memberId,
@@ -463,7 +466,10 @@ class MemberRepository {
463466
},
464467
)
465468

466-
if (mems.length > 0) {
469+
const hasMore = mems.length > pageLimit
470+
const pageRows = hasMore ? mems.slice(0, pageLimit) : mems
471+
472+
if (pageRows.length > 0) {
467473
let result
468474

469475
if (args.detail) {
@@ -522,7 +528,7 @@ class MemberRepository {
522528
}
523529
}
524530

525-
for (const mem of mems) {
531+
for (const mem of pageRows) {
526532
memberPromises.push(findMemberInfo(mem.id))
527533
toMergePromises.push(findMemberInfo(mem.toMergeId))
528534
}
@@ -532,10 +538,10 @@ class MemberRepository {
532538

533539
result = memberResults.map((i, idx) => ({
534540
members: [i, memberToMergeResults[idx]],
535-
similarity: mems[idx].similarity,
541+
similarity: pageRows[idx].similarity,
536542
}))
537543
} else {
538-
result = mems.map((i) => ({
544+
result = pageRows.map((i) => ({
539545
members: [
540546
{
541547
id: i.id,
@@ -554,12 +560,12 @@ class MemberRepository {
554560
}))
555561
}
556562

557-
return { rows: result, count: await getTotalCount(), limit: args.limit, offset: args.offset }
563+
return { rows: result, hasMore, limit: args.limit, offset: args.offset }
558564
}
559565

560566
return {
561567
rows: [{ members: [], similarity: 0 }],
562-
count: await getTotalCount(),
568+
hasMore: false,
563569
limit: args.limit,
564570
offset: args.offset,
565571
}

backend/src/database/repositories/organizationRepository.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,9 @@ class OrganizationRepository {
944944
return { count: await getTotalCount() }
945945
}
946946

947+
const pageLimit = args.limit
948+
const queryLimit = pageLimit + 1
949+
947950
const orgs = await options.database.sequelize.query(
948951
`
949952
SELECT
@@ -990,7 +993,7 @@ class OrganizationRepository {
990993
{
991994
replacements: {
992995
segmentIds,
993-
limit: args.limit,
996+
limit: queryLimit,
994997
offset: args.offset,
995998
displayName: args?.filter?.displayName ? `${args.filter.displayName}%` : undefined,
996999
mergeActionType: MergeActionType.ORG,
@@ -1001,14 +1004,17 @@ class OrganizationRepository {
10011004
},
10021005
)
10031006

1004-
if (orgs.length > 0) {
1007+
const hasMore = orgs.length > pageLimit
1008+
const pageRows = hasMore ? orgs.slice(0, pageLimit) : orgs
1009+
1010+
if (pageRows.length > 0) {
10051011
let result
10061012

10071013
if (args.detail) {
10081014
const organizationPromises = []
10091015
const toMergePromises = []
10101016

1011-
for (const org of orgs) {
1017+
for (const org of pageRows) {
10121018
organizationPromises.push(
10131019
OrganizationRepository.findById(org.id, options, org.primarySegmentId),
10141020
)
@@ -1022,10 +1028,10 @@ class OrganizationRepository {
10221028

10231029
result = organizationResults.map((i, idx) => ({
10241030
organizations: [i, organizationToMergeResults[idx]],
1025-
similarity: orgs[idx].similarity,
1031+
similarity: pageRows[idx].similarity,
10261032
}))
10271033
} else {
1028-
result = orgs.map((o) => ({
1034+
result = pageRows.map((o) => ({
10291035
organizations: [
10301036
{
10311037
id: o.id,
@@ -1055,15 +1061,15 @@ class OrganizationRepository {
10551061

10561062
return {
10571063
rows: result,
1058-
count: await getTotalCount(),
1064+
hasMore,
10591065
limit: args.limit,
10601066
offset: args.offset,
10611067
}
10621068
}
10631069

10641070
return {
10651071
rows: [{ organizations: [], similarity: 0 }],
1066-
count: await getTotalCount(),
1072+
hasMore: false,
10671073
limit: args.limit,
10681074
offset: args.offset,
10691075
}

frontend/src/modules/data-quality/components/member/data-quality-member-merge-suggestions.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</div>
1919
</template>
2020
</lf-data-quality-member-merge-suggestions-item>
21-
<div v-if="mergeSuggestions.length < total" class="pt-4">
21+
<div v-if="hasMore" class="pt-4">
2222
<lf-button
2323
type="primary-ghost"
2424
loading-text="Loading suggestions..."
@@ -73,7 +73,7 @@ const props = defineProps<{
7373
const loading = ref(true);
7474
const limit = ref(20);
7575
const offset = ref(0);
76-
const total = ref(0);
76+
const hasMore = ref(false);
7777
const mergeSuggestions = ref<any[]>([]);
7878
7979
const isModalOpen = ref<boolean>(false);
@@ -91,7 +91,7 @@ const loadMergeSuggestions = () => {
9191
segments: segments.value,
9292
})
9393
.then((res) => {
94-
total.value = +res.count;
94+
hasMore.value = Boolean(res.hasMore);
9595
const rows = res.rows.filter((s: any) => s.similarity > 0);
9696
if (+res.offset > 0) {
9797
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];

frontend/src/modules/data-quality/components/organization/data-quality-organization-merge-suggestions.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</lf-button>
1616
</template>
1717
</lf-data-quality-organization-merge-suggestions-item>
18-
<div v-if="mergeSuggestions.length < total" class="pt-4">
18+
<div v-if="hasMore" class="pt-4">
1919
<lf-button
2020
type="primary-ghost"
2121
loading-text="Loading suggestions..."
@@ -67,7 +67,7 @@ const props = defineProps<{
6767
const loading = ref(true);
6868
const limit = ref(20);
6969
const offset = ref(0);
70-
const total = ref(0);
70+
const hasMore = ref(false);
7171
const mergeSuggestions = ref<any[]>([]);
7272
7373
const isModalOpen = ref<boolean>(false);
@@ -84,7 +84,7 @@ const loadMergeSuggestions = () => {
8484
orderBy: ['similarity_DESC', 'activityCount_DESC'],
8585
})
8686
.then((res) => {
87-
total.value = +res.count;
87+
hasMore.value = Boolean(res.hasMore);
8888
const rows = res.rows.filter((s: any) => s.similarity > 0);
8989
if (+res.offset > 0) {
9090
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];

frontend/src/modules/member/components/member-merge-suggestions.vue

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<lf-button
88
type="secondary"
99
size="small"
10-
:disabled="loading || offset <= 0 || count === 0"
10+
:disabled="loading || offset <= 0 || !hasSuggestion"
1111
:icon-only="true"
1212
@click="fetch(offset - 1)"
1313
>
@@ -16,7 +16,7 @@
1616
<lf-button
1717
type="secondary"
1818
size="small"
19-
:disabled="loading || offset >= count - 1 || count === 0"
19+
:disabled="loading || !hasMore"
2020
:icon-only="true"
2121
@click="fetch(offset + 1)"
2222
>
@@ -26,16 +26,10 @@
2626

2727
<app-loading v-if="loading" height="16px" width="128px" radius="3px" />
2828
<div
29-
v-else-if="Math.ceil(count) > 1"
29+
v-else-if="hasSuggestion"
3030
class="text-xs leading-5 text-gray-500"
3131
>
32-
<div>{{ offset + 1 }} of {{ Math.ceil(count) }} suggestions</div>
33-
</div>
34-
<div
35-
v-else-if="Math.ceil(count) === 1"
36-
class="text-xs leading-5 text-gray-500"
37-
>
38-
<div>1 suggestion</div>
32+
<div>Suggestion {{ offset + 1 }}</div>
3933
</div>
4034
<div
4135
v-else
@@ -48,15 +42,15 @@
4842
<app-member-merge-similarity v-if="!loading && membersToMerge.similarity" :similarity="membersToMerge.similarity" />
4943
<lf-button
5044
type="secondary"
51-
:disabled="loading || isEditLockedForSampleData || count === 0"
45+
:disabled="loading || isEditLockedForSampleData || !hasSuggestion"
5246
:loading="sendingIgnore"
5347
@click="ignoreSuggestion()"
5448
>
5549
Ignore suggestion
5650
</lf-button>
5751
<lf-button
5852
type="primary"
59-
:disabled="loading || isEditLockedForSampleData || count === 0"
53+
:disabled="loading || isEditLockedForSampleData || !hasSuggestion"
6054
:loading="sendingMerge"
6155
@click="mergeSuggestion()"
6256
>
@@ -66,7 +60,7 @@
6660
</div>
6761
</header>
6862

69-
<div v-if="loading || count > 0">
63+
<div v-if="loading || hasSuggestion">
7064
<!-- Comparison -->
7165
<!-- Loading -->
7266
<div v-if="loading" class="flex p-5">
@@ -170,7 +164,8 @@ const { getContributorMergeActions } = useContributorStore();
170164
const membersToMerge = ref([]);
171165
const primary = ref(0);
172166
const offset = ref(props.offset);
173-
const count = ref(0);
167+
const hasMore = ref(false);
168+
const hasSuggestion = ref(false);
174169
const loading = ref(false);
175170
176171
const sendingIgnore = ref(false);
@@ -204,25 +199,45 @@ const preview = computed(() => {
204199
return mergedMembers;
205200
});
206201
207-
const fetch = (page) => {
202+
const updateSuggestionsState = (res) => {
203+
hasMore.value = Boolean(res.hasMore);
204+
const rows = res.rows.filter((suggestion) => suggestion.similarity > 0);
205+
206+
if (rows.length > 0) {
207+
hasSuggestion.value = true;
208+
[membersToMerge.value] = rows;
209+
} else {
210+
hasSuggestion.value = false;
211+
membersToMerge.value = [];
212+
}
213+
};
214+
215+
const fetch = (page, trackNavigation = true) => {
208216
if (page > -1) {
209217
offset.value = page;
210218
}
211219
212-
trackEvent({
213-
key: FeatureEventKey.NAVIGATE_MEMBERS_MERGE_SUGGESTIONS,
214-
type: EventType.FEATURE,
215-
});
220+
if (trackNavigation) {
221+
trackEvent({
222+
key: FeatureEventKey.NAVIGATE_MEMBERS_MERGE_SUGGESTIONS,
223+
type: EventType.FEATURE,
224+
});
225+
}
216226
217227
loading.value = true;
218228
219-
MemberService.fetchMergeSuggestions(1, offset.value, props.query ?? {})
229+
return MemberService.fetchMergeSuggestions(1, offset.value, props.query ?? {})
220230
.then((res) => {
221231
offset.value = +res.offset;
222-
count.value = res.count;
223-
[membersToMerge.value] = res.rows;
232+
233+
updateSuggestionsState(res);
234+
235+
if (!hasSuggestion.value && offset.value > 0) {
236+
return fetch(offset.value - 1, false);
237+
}
224238
225239
primary.value = 0;
240+
return undefined;
226241
})
227242
.catch(() => {
228243
ToastStore.error(
@@ -252,8 +267,7 @@ const ignoreSuggestion = () => {
252267
.then(() => {
253268
ToastStore.success('Merging suggestion ignored successfully');
254269
getContributorMergeActions();
255-
const nextIndex = offset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : offset.value;
256-
fetch(nextIndex);
270+
fetch(offset.value);
257271
changed.value = true;
258272
})
259273
.catch((error) => {
@@ -304,8 +318,7 @@ const mergeSuggestion = () => {
304318
);
305319
primary.value = 0;
306320
307-
const nextIndex = offset.value >= (count.value - 1) ? Math.max(count.value - 2, 0) : offset.value;
308-
fetch(nextIndex);
321+
fetch(offset.value);
309322
changed.value = true;
310323
})
311324
.catch((error) => {

frontend/src/modules/member/pages/member-merge-suggestions-page.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@
114114
</p>
115115
</div>
116116

117-
<div v-if="total > mergeSuggestions.length" class="mt-6 flex justify-center">
117+
<div v-if="hasMore" class="mt-6 flex justify-center">
118118
<lf-button type="primary-ghost" size="small" :loading="loading" @click="loadMore()">
119119
<lf-icon name="arrow-down" />Load more
120120
</lf-button>
@@ -158,7 +158,7 @@ const mergeSuggestions = ref<any[]>([]);
158158
159159
const isModalOpen = ref<boolean>(false);
160160
161-
const total = ref<number>(0);
161+
const hasMore = ref<boolean>(false);
162162
const limit = ref<number>(10);
163163
const page = ref<number>(1);
164164
const loading = ref<boolean>(false);
@@ -187,7 +187,7 @@ const loadMergeSuggestions = (sort: boolean = false) => {
187187
detail: false,
188188
})
189189
.then((res) => {
190-
total.value = +res.count;
190+
hasMore.value = Boolean(res.hasMore);
191191
const rows = res.rows.filter((s: any) => s.similarity > 0);
192192
if (+res.offset > 0) {
193193
mergeSuggestions.value = [...mergeSuggestions.value, ...rows];

0 commit comments

Comments
 (0)