Reputation: 801
I have been trying to find a way in which the documents from a collection in firestore can get deleted after a certain amount of time in my case 24h, for doing this I realized that I have to use firebase cloud functions so after investigating I found this post which does the work that I need to add in my project except that I am using typescript instead of javascript which is being used in that question and I cant change it to javascript because I am already using typescipt for sending notifications to users. How can I change the following code to typescript?
//index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp()
const db = admin.firestore();
export const deleteOldItems = functions.database
.ref('stories/{storyId}')
.onWrite((change, context) => {
var ref = change.after.ref.parent;
var now = Date.now();
var cutoff = now - 24 * 60 * 60 * 1000;
var oldItemsQuery = ref.orderByChild('created').endAt(cutoff);
return oldItemsQuery.once('value', function(snapshot) {
// create a map with all children that need to be removed
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null
});
// execute all updates in one go and return the result to end the function
return ref.update(updates);
});
});
here is an image of the data that needs to be erased after 24h, created field is the date when the document was created and deleted id the date where the doc should be deleted.
EDIT: I turns out the problem is not because of using typescript but because I am using firestore instead of firebase real time database so I created this code which is supposed to make things work but it doesnt. How can I fix this?
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp()
const db = admin.firestore();
export const deleteOldItems = functions.firestore
.document('stories/{storyId}')
.onWrite(async (change, context) => {
const getData = await db.collection('stories').where('deleted', '>', Date.now()).get().then(
(snapshot) => snapshot.forEach((doc) =>
doc.ref.delete()
)
);
return getData;
});
Upvotes: 1
Views: 937
Reputation: 83103
You are mixing async/await
with then
and, in addition, you are not waiting that the set of calls to the delete()
asynchronous method are all completed. So the Cloud Function platform may clean up the Cloud Function instance before all the work is done. You need to wait that all this asynchronous work is done before returning a Promise or a value. More details here in the doc.
The following should do the trick:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp()
const db = admin.firestore();
export const deleteOldItems = functions.firestore
.document('stories/{storyId}')
.onWrite(async (change, context) => {
const querySnapshot = await db.collection('stories').where('deleted', '>', Date.now()).get();
const promises = [];
querySnapshot.forEach((doc) => {
promises.push(doc.ref.delete());
});
return Promise.all(promises);
});
Since you want to delete a variable number of documents, you need to use Promise.all()
to execute in parallel the asynchronous deletion tasks (Since the delete()
method returns a Promise).
Updates following you questions in the comments below:
1/ Promise.all()
returns a single Promise that resolves to an array of the results of the input promises. This returned promise will resolve when all of the promises in the array have resolved. The main interest of Promise.all()
is that it returns a single Promise, therefore you can easily know when all the calls to the asynchronous delete()
method (which returns a Promise) are done.
2/ The onWrite
event type is triggered when a doc is created, modified or deleted. Since you used this event type in your question I kept it. If you want to schedule the execution, use a scheduled Cloud Function. The "inner code" is exactly the same.
Upvotes: 2
Reputation: 429
I think that ".onWrite(async (change, context) " its only called when the document is created, you need to create a task every x time to check If there is a document to delete, then you make the query and delete de document.
You can use Cron job from you server o task scheduler, I think google cloud have its own task scheduler.
A functions can not last more than 60 seconds, after that sent an error.
Upvotes: 0