I'm trying to create a simple Firebase extension. I have a few Cloud functions that work fine and I also enabled the option to backfill existing users. This means that when someone installs the extension, I will add a ranking (number) in the Realtime Database.
This is what I have tried. In my extension.yaml file, I have added:
- name: backfillDocs
type: firebaseextensions.v1beta.function
description: >-
Rank users
properties:
runtime: "nodejs16"
taskQueueTrigger: {}
And I want to do that on install:
lifecycleEvents:
onInstall:
function: backfillDocs
processingMessage: Setting the rank.
I checked the docs, and here is what I have tried with my function:
exports.backfillDocs = tasks
.taskQueue()
.onDispatch(async (data) => {
const offset = data["offset"] !== undefined ? data["offset"] : 0;
const snapshot = await getFirestore()
.collection("users")
.limit(DOCS_PER_BACKFILL)
.get();
const processed = await Promise.allSettled(
snapshot.docs.map(async (doc) => {
const ref = getDatabase().ref().child("rankings").child(doc.id);
await ref.set(0);
}),
);
if (processed.length == DOCS_PER_BACKFILL) {
const queue = getFunctions().taskQueue(
"backfilldata",
process.env.EXT_INSTANCE_ID,
);
return await queue.enqueue({
offset: offset + DOCS_PER_BACKFILL,
});
} else {
return getExtensions().runtime()
.setProcessingState(
"PROCESSING_COMPLETE",
"Backfill complete.",
);
}
});
The problem is that, each time I install the extension, I get:
Error: The principal (user or service account) lacks IAM permission "cloudtasks.tasks.create"
I don't see why I get this error since I have enabled Cloud Tasks Enqueuer
to project-id@appspot.gserviceaccount.com
, firebase-adminsdk-*****@project-id.iam.gserviceaccount.com
and firebase-service-account@firebase-sa-management.iam.gserviceaccount.com
. Here is a screenshot:
What am I missing? Please help.
The queue name in the code must match the function name. It appears your function is called doBackfillExistingDocuments
so when getting the queue ref you need to use the same name:
exports.doBackfillExistingDocuments = tasks
.taskQueue()
.onDispatch(async (data) => {
// ...
const queue = getFunctions().taskQueue(
"doBackfillExistingDocuments", // <----
process.env.EXT_INSTANCE_ID,
);
// ...
});