I am trying to update lastMessage on a chatRoom, So every time a message is created in the subcollection of the chat room it sets it as lastMessage on the chatRoom.
In order to avoid unnecessary writes on Firestore I want to use Google tasks with a handler.
Google tasks queues can delete existing tasks, so I thought to assign the room ID to the task and if you write 15 messages in 1 minute only the last one will have the update.
The problem
When I have executed a task with the chatRoomId, this task block any other creation despite of delete(id) is successful even hours later
things I tried
- adding a prefix to the chatRoomId for the task works for the first message
- I have checked the task console and no task to delete is there, but the error on
.upsertremains onException from a finished function: Error: A task with ID abcde1234 already exists
My approach
import { onTaskDispatched } from "firebase-functions/v2/tasks";
import { TaskOptions, getFunctions } from "firebase-admin/functions";
export const taskHandler = onTaskDispatched(
{
retryConfig: {
maxAttempts: 3,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
},
async (req) => {
const lastMessage = req.data;
// the second message doesn't arrive here
console.log("lastMessage", lastMessage);
}
);
// A function to import to use admin the queue
// To be used
export function tasks() {
const queue = getFunctions().taskQueue("taskHandler");
async function create(args) {
const { id, seconds: scheduleDelaySeconds, data } = args;
const options: TaskOptions = {
id,
scheduleDelaySeconds,
};
queue.enqueue(data, options);
}
async function upsert(args) {
const { id = "" } = args;
if (!id) return create(args);
await queue.delete(id);
await create(args);
}
return { upsert, create };
}
// usage example
// firestore triggers a function on create message
const exampleMessage = { text: "hello", created: Date.now() };
tasks().upsert({
id: "chatRoomId",
seconds: 60,
data: exampleMessage,
});