Skip to content

Commit 34d91b6

Browse files
committed
ensuring we're not looping over same users during cleanOutdatedUsers()
1 parent e61d2c3 commit 34d91b6

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

cloud/functions/src/functions/firestore/migrations/025-fillUserLastConnection.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import {FieldPath} from "firebase-admin/firestore";
1010
export async function fillUserLastConnection(): Promise<"OK"|"Error"> {
1111
let updateCounts = 0
1212
const stats = await windowedProcessUsers(
13-
(maybePreviousResults) => match(maybePreviousResults)
13+
(maybeLastPreviousUserDoc) => match(maybeLastPreviousUserDoc)
1414
.with(P.nullish, () => db.collection('users'))
15-
.otherwise(previousResults => db.collection('users').where(FieldPath.documentId(), '>', previousResults.docs[previousResults.docs.length-1].id)),
15+
.otherwise(lastPreviousUserDoc => db.collection('users').where(FieldPath.documentId(), '>', lastPreviousUserDoc.id))
16+
.orderBy(FieldPath.documentId(), 'asc'),
1617
async userDoc => {
1718
const user = userDoc.data();
1819
if(!user.userLastConnection) {

cloud/functions/src/functions/firestore/services/user-utils.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import QuerySnapshot = firestore.QuerySnapshot;
1010
import {User} from "../../../../../../shared/user.firestore";
1111
import {UserTokensWallet} from "../../../../../../shared/user-tokens-wallet.localstorage";
1212
import DocumentSnapshot = firestore.DocumentSnapshot;
13+
import {match, P} from "ts-pattern";
14+
import {FieldPath} from "firebase-admin/firestore";
1315

1416

1517
async function getRawUsersMatching(collectionFilter: (collection: CollectionReference) => Query) {
@@ -30,11 +32,18 @@ export async function cleanOutdatedUsers() {
3032
const MAXIMUM_NUMBER_OF_FEEDBACKS = 0;
3133

3234
const stats = await windowedProcessUsers(
33-
() => db.collection(`/users`)
34-
.where(`totalFavs.total`, '<=', MAXIMUM_NUMBER_OF_FAVS)
35-
.where(`totalFeedbacks.total`, '<=', MAXIMUM_NUMBER_OF_FEEDBACKS)
36-
.where(`userLastConnection`, '<', oldestValidLastConnectionDate),
37-
(userDoc) => deleteUserRefIncludingChildren(userDoc.ref),
35+
(maybePreviousResults) => {
36+
const baseQuery = db.collection(`/users`)
37+
.where(`totalFavs.total`, '<=', MAXIMUM_NUMBER_OF_FAVS)
38+
.where(`totalFeedbacks.total`, '<=', MAXIMUM_NUMBER_OF_FEEDBACKS)
39+
.where(`userLastConnection`, '<', oldestValidLastConnectionDate)
40+
return match(maybePreviousResults)
41+
.with(P.nullish,
42+
() => baseQuery
43+
).otherwise(maybeLastPreviousUserDoc => baseQuery.where(FieldPath.documentId(), '>', maybeLastPreviousUserDoc.id))
44+
.orderBy(FieldPath.documentId(), 'asc')
45+
},
46+
userDoc => deleteUserRefIncludingChildren(userDoc.ref),
3847
)
3948

4049
return {
@@ -49,7 +58,7 @@ type UserOpsDuration = { type: string, duration: number }
4958
export type WindowedProcessUsersStats = {durations: Array<UserOpsDuration>, totalDuration: number, successes: number, failures: number}
5059

5160
export async function windowedProcessUsers(
52-
userQueryFactory: (maybePreviousResults: undefined|QuerySnapshot<User>) => Query,
61+
userQueryFactory: (maybeLastPreviousUserDoc: undefined|QueryDocumentSnapshot<User>, maybePreviousResults: undefined|QuerySnapshot<User>) => Query,
5362
processUserCallback: (userDoc: QueryDocumentSnapshot<User>, stats: WindowedProcessUsersStats) => Promise<void>,
5463
{maxWindowSize, resultsProcessor}: {
5564
maxWindowSize: number,
@@ -66,7 +75,7 @@ export async function windowedProcessUsers(
6675
const fetchNextUsersWindow = async (maybePreviousResults: undefined|QuerySnapshot<User>) => {
6776
return (await durationOf(
6877
() =>
69-
userQueryFactory(maybePreviousResults).limit(maxWindowSize).get() as Promise<QuerySnapshot<User>>,
78+
userQueryFactory(maybePreviousResults ? maybePreviousResults.docs[maybePreviousResults.docs.length-1]:undefined, maybePreviousResults).limit(maxWindowSize).get() as Promise<QuerySnapshot<User>>,
7079
({durationInMillis}) => {
7180
stats.durations.push({type: 'fetchingWindowedUsers', duration: durationInMillis});
7281
stats.totalDuration += durationInMillis;

0 commit comments

Comments
 (0)