Skip to content

Commit f67c7d1

Browse files
committed
introduced dryRun and force query params on cleanOutdatedUsers
1 parent 34d91b6 commit f67c7d1

File tree

3 files changed

+37
-27
lines changed

3 files changed

+37
-27
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {cleanOutdatedUsers as cleanOutdatedUsersService} from "../functions/firestore/services/user-utils";
22

33

4-
export async function cleanOutdatedUsers() {
5-
return await cleanOutdatedUsersService();
4+
export async function cleanOutdatedUsers(opts: { force: boolean, dryRun: boolean } = { force: false, dryRun: false }) {
5+
return await cleanOutdatedUsersService(opts);
66
}

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

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function getUserDocsMatching(collectionFilter: (collection: Collect
2626
return (await getRawUsersMatching(collectionFilter));
2727
}
2828

29-
export async function cleanOutdatedUsers() {
29+
export async function cleanOutdatedUsers(opts: { force: boolean, dryRun: boolean } = { force: false, dryRun: false }) {
3030
const oldestValidLastConnectionDate = Temporal.Now.zonedDateTimeISO().subtract({months: 2}).toString() as ISODatetime
3131
const MAXIMUM_NUMBER_OF_FAVS = 0;
3232
const MAXIMUM_NUMBER_OF_FEEDBACKS = 0;
@@ -43,7 +43,7 @@ export async function cleanOutdatedUsers() {
4343
).otherwise(maybeLastPreviousUserDoc => baseQuery.where(FieldPath.documentId(), '>', maybeLastPreviousUserDoc.id))
4444
.orderBy(FieldPath.documentId(), 'asc')
4545
},
46-
userDoc => deleteUserRefIncludingChildren(userDoc.ref),
46+
userDoc => deleteUserRefIncludingChildren(userDoc.ref, opts),
4747
)
4848

4949
return {
@@ -123,7 +123,7 @@ export async function windowedProcessUsers(
123123
return stats;
124124
}
125125

126-
async function deleteUserRefIncludingChildren(userRef: DocumentReference<DocumentData>, force = false) {
126+
async function deleteUserRefIncludingChildren(userRef: DocumentReference<DocumentData>, {force, dryRun}: { force: boolean, dryRun: boolean } = { force: false, dryRun: false }) {
127127
const tokensWalletDoc = await db.doc(`${userRef.path}/tokens-wallet/self`).get() as DocumentSnapshot<UserTokensWallet>
128128
const walletSecrets = tokensWalletDoc.data()?.secretTokens;
129129

@@ -139,59 +139,65 @@ async function deleteUserRefIncludingChildren(userRef: DocumentReference<Documen
139139
const preferencesDoc = await db.doc(`${userRef.path}/preferences/self`).get()
140140

141141
await Promise.all([
142-
deleteUserSpaces(userRef),
143-
deleteUserEventsFromNode(userRef),
144-
...(preferencesDoc.exists ? [preferencesDoc.ref.delete()]:[]),
145-
...(tokensWalletDoc.exists ? [tokensWalletDoc.ref.delete()]:[]),
142+
deleteUserSpaces(userRef, { dryRun }),
143+
deleteUserEventsFromNode(userRef, { dryRun }),
144+
...((preferencesDoc.exists && !dryRun) ? [preferencesDoc.ref.delete()]:[]),
145+
...((tokensWalletDoc.exists && !dryRun) ? [tokensWalletDoc.ref.delete()]:[]),
146146
])
147147

148148
console.info(`Deleting user entry ${userRef.path}`)
149-
await userRef.delete()
149+
if(!dryRun) {
150+
await userRef.delete()
151+
}
150152
}
151153

152-
async function deleteUserEventsFromNode(rootRef: DocumentReference) {
154+
async function deleteUserEventsFromNode(rootRef: DocumentReference, {dryRun}: { dryRun: boolean } = { dryRun: false }) {
153155
const eventRefs = await db.collection(`${rootRef.path}/events`).listDocuments();
154156

155157
await Promise.all(eventRefs.map(async eventRef => {
156158
console.debug(`Deleting user event entry ${eventRef.path}...`)
157159
return Promise.all([
158-
deleteUserTalkNotesFromEvent(eventRef),
159-
deleteUserDailyFeedbacksFromEvent(eventRef),
160-
eventRef.delete(),
160+
deleteUserTalkNotesFromEvent(eventRef, { dryRun }),
161+
deleteUserDailyFeedbacksFromEvent(eventRef, { dryRun }),
162+
...(!dryRun ? [eventRef.delete()]:[]),
161163
])
162164
}))
163165
}
164166

165-
async function deleteUserSpaces(userRef: DocumentReference<DocumentData>) {
167+
async function deleteUserSpaces(userRef: DocumentReference<DocumentData>, {dryRun}: { dryRun: boolean } = { dryRun: false }) {
166168
const spaceRefs = await db.collection(`${userRef.path}/spaces`).listDocuments()
167169

168170
await Promise.all(spaceRefs.map(async spaceRef => {
169171
console.debug(`Deleting user space entry ${spaceRef.path}...`)
170172
return Promise.all([
171-
deleteUserEventsFromNode(spaceRef),
172-
spaceRef.delete(),
173+
deleteUserEventsFromNode(spaceRef, { dryRun }),
174+
...(!dryRun ? [spaceRef.delete()]:[]),
173175
])
174176
}))
175177
}
176178

177-
async function deleteUserTalkNotesFromEvent(eventRef: DocumentReference<DocumentData>) {
179+
async function deleteUserTalkNotesFromEvent(eventRef: DocumentReference<DocumentData>, {dryRun}: { dryRun: boolean } = { dryRun: false }) {
178180
const talkNotesRefs = await db.collection(`${eventRef.path}/talksNotes`).listDocuments()
179181

180182
await Promise.all(talkNotesRefs.map(async talkNotesRef => {
181183
console.debug(`Deleting user talk notes entry ${talkNotesRef.path}...`)
182-
return talkNotesRef.delete()
184+
if(!dryRun) {
185+
await talkNotesRef.delete()
186+
}
183187
}))
184188
}
185189

186-
async function deleteUserDailyFeedbacksFromEvent(eventRef: DocumentReference<DocumentData>) {
190+
async function deleteUserDailyFeedbacksFromEvent(eventRef: DocumentReference<DocumentData>, {dryRun}: { dryRun: boolean } = { dryRun: false }) {
187191
const dailyFeedbackRefs = await db.collection(`${eventRef.path}/days`).listDocuments()
188192

189193
await Promise.all(dailyFeedbackRefs.map(async dailyFeedbackRef => {
190194
console.debug(`Deleting user daily feedback entry ${dailyFeedbackRef.path}...`)
191-
return Promise.all([
192-
db.doc(`${dailyFeedbackRef.path}/feedbacks/self`).delete(),
193-
dailyFeedbackRef.delete(),
194-
])
195+
if(!dryRun) {
196+
await Promise.all([
197+
db.doc(`${dailyFeedbackRef.path}/feedbacks/self`).delete(),
198+
dailyFeedbackRef.delete(),
199+
])
200+
}
195201
}))
196202
}
197203

cloud/functions/src/functions/http/api/admin-routes.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ export function declareAdminHttpRoutes(app: Express) {
2222

2323
Routes.post(app, `/cron/cleanOutdatedUsers`,
2424
z.object({
25-
query: z.object({ token: z.string() })
25+
query: z.object({
26+
token: z.string(),
27+
dryRun: z.boolean().default(false),
28+
force: z.boolean().default(false),
29+
})
2630
}),
2731
ensureHasSuperAdminToken(),
28-
async (res, path, query, body) => {
29-
const results = await (await import("../../../cron/cleanOutdatedUsers")).cleanOutdatedUsers();
32+
async (res, path, { dryRun, force }, body) => {
33+
const results = await (await import("../../../cron/cleanOutdatedUsers")).cleanOutdatedUsers({ dryRun, force });
3034
return sendResponseMessage(res, 200, {
3135
message: `${results.totalDeletedUsers} users have been deleted (in ${results.totalDuration}ms) !`,
3236
results

0 commit comments

Comments
 (0)