0
votes

I want to write cloud function for Firestore which will decrement task.elapsedCount and make user.points += 3 in two parallel threads:

exports.taskDoneFunc = functions.firestore
.document('/tasks/{taskId}')
.onUpdate(event => {

    const taskRef = event.data.ref;
    const root = taskRef.root;

    return taskRef.get()
        .then(taskSnap => {

            let task = taskSnap.data();

            task.elapsedCount -= 1;

            taskRef.set(task, {merge: true})

            return root.document('/users/${task.taskOwner_uid}').get()

        }).then(userSnap => {

            let user = userSnap.data();

            user.points += 3;

            return userSnap.ref.set(user)

        })
});

first Promise works fine and I see changes in task Firestore "task" document, but second says "Cannot read property 'document' of undefined".
I've not found any clean examples for Cloud Functions for Firestore database triggers, this is crazy Beta? :(

2

2 Answers

1
votes

I don't believe root is defined in a Firestore DocumentReference (docs). Instead, I believe you want to use firestore(docs), which gets the top level Firestore database:

exports.taskDoneFunc = functions.firestore
.document('/tasks/{taskId}')
.onUpdate(event => {

    const taskRef = event.data.ref;
    const db = taskRef.firestore;
    const task;

    return taskRef.get()
        .then(taskSnap => {
            task = taskSnap.data();
            task.elapsedCount -= 1;
            return taskRef.set(task, {merge: true})
        }).then(() => {
            return db.collection('users').doc(task.taskOwner_uid).get();
        }).then(userSnap => {
            let user = userSnap.data();
            user.points += 3;
            return userSnap.ref.set(user)
        })
});

I think there was also a potential race condition with two async functions (the set followed by the get).

0
votes

I've just figured out howTo work with functions in Firestore: just

admin.firestore().doc(/users/${uid}).get()

-like calls. If it will be helpful for someone :)