11import { onDocumentDeleted , onDocumentUpdated } from "firebase-functions/v2/firestore" ;
2+ import { onSchedule } from "firebase-functions/v2/scheduler" ;
23import * as admin from "firebase-admin" ;
34import * as logger from "firebase-functions/logger" ;
45
56const LOCATION = "asia-northeast3" ;
67const DELETE_BATCH_SIZE = 200 ;
8+ const CLEANUP_QUERY_BATCH_SIZE = 100 ;
79
8- export const deleteTodoNotificationReceipts = onDocumentDeleted ( {
10+ export const removeTodoNotificationDocuments = onDocumentDeleted ( {
911 document : "users/{userId}/todoLists/{todoId}" ,
1012 region : LOCATION
1113 } ,
@@ -26,7 +28,7 @@ export const deleteTodoNotificationReceipts = onDocumentDeleted({
2628 }
2729) ;
2830
29- export const deleteCompletedTodoReceipts = onDocumentUpdated ( {
31+ export const removeCompletedTodoReceipts = onDocumentUpdated ( {
3032 document : "users/{userId}/todoLists/{todoId}" ,
3133 region : LOCATION
3234 } ,
@@ -61,6 +63,48 @@ export const deleteCompletedTodoReceipts = onDocumentUpdated({
6163 }
6264) ;
6365
66+ export const removeExpiredCompletedTodoReceipts = onSchedule ( {
67+ region : LOCATION ,
68+ schedule : "0 * * * *" ,
69+ timeZone : "UTC"
70+ } ,
71+ async ( ) => {
72+ try {
73+ let lastDoc : FirebaseFirestore . QueryDocumentSnapshot < FirebaseFirestore . DocumentData > | undefined ;
74+
75+ while ( true ) {
76+ let query = admin . firestore ( )
77+ . collectionGroup ( "todoLists" )
78+ . where ( "dueDate" , "<" , admin . firestore . Timestamp . now ( ) )
79+ . orderBy ( "dueDate" )
80+ . limit ( CLEANUP_QUERY_BATCH_SIZE ) ;
81+
82+ if ( lastDoc ) {
83+ query = query . startAfter ( lastDoc ) ;
84+ }
85+
86+ const snapshot = await query . get ( ) ;
87+ if ( snapshot . empty ) { return ; }
88+
89+ for ( const todoDoc of snapshot . docs ) {
90+ const todoData = todoDoc . data ( ) ;
91+ if ( todoData . isCompleted !== true ) { continue ; }
92+
93+ const userId = todoDoc . ref . parent . parent ?. id ;
94+ if ( ! userId ) { continue ; }
95+
96+ await deleteByTodoId ( userId , "notificationReceipts" , todoDoc . id ) ;
97+ }
98+
99+ if ( snapshot . size < CLEANUP_QUERY_BATCH_SIZE ) { return ; }
100+ lastDoc = snapshot . docs [ snapshot . docs . length - 1 ] ;
101+ }
102+ } catch ( error ) {
103+ logger . error ( "지난 마감일의 완료된 todo receipt 정리 실패" , { error } ) ;
104+ }
105+ }
106+ ) ;
107+
64108async function deleteByTodoId (
65109 userId : string ,
66110 collectionName : "notificationReceipts" | "notifications" ,
0 commit comments