Cloud Tasks
Firenook’s Cloud Tasks emulator gives every onTaskDispatched function its
queue and dispatches tasks to it with the official emulator’s retries and
rate limits. Read this page to enqueue tasks from your code and your scripts,
and to see how retries behave.
Set it up
Section titled “Set it up”Cloud Tasks runs with Functions; there is nothing to add but its port, which defaults to 9499:
{ "emulators": { "tasks": { "port": 9499 } }}Each onTaskDispatched export gets a queue when your functions load:
firenook tasks: Created queue with key: queue:demo-shop-us-central1-sendReceiptEnqueue a task
Section titled “Enqueue a task”A task queue function and an HTTP function that enqueues for it:
const { onRequest } = require('firebase-functions/https');const { onTaskDispatched } = require('firebase-functions/tasks');const logger = require('firebase-functions/logger');const { getFunctions } = require('firebase-admin/functions');
exports.sendReceipt = onTaskDispatched( { retryConfig: { maxAttempts: 3, minBackoffSeconds: 1 }, rateLimits: { maxConcurrentDispatches: 2 } }, async (request) => { logger.info('task', { data: request.data, retryCount: request.retryCount }); },);
exports.enqueueReceipt = onRequest(async (req, res) => { await getFunctions().taskQueue('sendReceipt').enqueue({ orderId: req.query.order }); res.send('queued');});The Admin SDK finds the emulator through CLOUD_TASKS_EMULATOR_HOST.
Firenook sets it inside Functions, and firenook emulators:exec sets it for
its command, as the official emulators:exec does. A script that enqueues,
run under exec, and the function it reaches (trimmed to the task):
import { initializeApp } from 'firebase-admin/app';import { getFunctions } from 'firebase-admin/functions';
initializeApp({ projectId: 'demo-shop' });await getFunctions().taskQueue('sendReceipt').enqueue({ orderId: 'o50' }, { id: 'receipt-o50' });console.log('enqueued receipt-o50');$ npx firenook emulators:exec "node enqueue.mjs && sleep 1"All emulators readyenqueued receipt-o50firenook functions: Beginning execution of "us-central1-sendReceipt"firenook functions: {"data":{"orderId":"o50"},"retryCount":0,"severity":"INFO","message":"task"}The sleep keeps the emulators up until the task has run; a test waits for
what the task does instead. A script you run by hand sets
CLOUD_TASKS_EMULATOR_HOST=127.0.0.1:9499 itself. firenook functions:invoke sendReceipt --event-data '{"orderId":"o8"}' enqueues a task the same way,
through this emulator.
Retries and rate limits
Section titled “Retries and rate limits”A task whose function fails, or answers anything but a 2xx status, is retried
with the backoff its retryConfig sets. The emulator reproduces the official
one’s ladder, including its off-by-one: a queue with maxAttempts: 3 runs a
failing task four times.
firenook functions: {"retryCount":0,"executionCount":0,"severity":"INFO","message":"charge attempt"}firenook functions: {"retryCount":1,"executionCount":0,"severity":"INFO","message":"charge attempt"}firenook functions: {"retryCount":2,"executionCount":0,"severity":"INFO","message":"charge attempt"}firenook functions: {"retryCount":3,"executionCount":0,"severity":"INFO","message":"charge attempt"}maxRetrySeconds keeps a task retrying past maxAttempts until its time runs
out. rateLimits caps how many tasks run at once (maxConcurrentDispatches)
and how many start each second (maxDispatchesPerSecond), and a task
enqueued with dispatchDeadlineSeconds gets that long for each attempt.
Every dispatch carries the X-CloudTasks-* headers Cloud Tasks sends.
GET /queueStats on the Tasks port reports each queue:
$ curl http://127.0.0.1:9499/queueStats{"queue:demo-shop-us-central1-sendReceipt":{"numberOfTasks":0,"tasksAdded":0.2,"completedLastMin":1,"failedTasks":0,"runningTasks":2,"maxRate":500,"maxConcurrent":2}}The official emulator’s quirks, kept
Section titled “The official emulator’s quirks, kept”These come from the official emulator and are kept on purpose, because clients and tests can see them:
runningTasksis the number of dispatch slots, that ismaxConcurrentDispatches, not the tasks running now.tasksAddedandfailedTasksare five-minute counts divided by five;completedLastMincounts one minute.- A
scheduleTimenever delays a task. - A generated task name starts with a slash, while a delete builds the name
without one, so a task with a generated name cannot be deleted. Name your
tasks (
enqueue(data, { id })) if you delete them. - A 5xx answer leaves
executionCountas it is; any other failure adds one. - Registering a queue again, as a reload does, replaces it and drops its pending tasks.
What it does not do
Section titled “What it does not do”The same things the official emulator does not: no scheduleTime delay, no
OIDC tokens, no queue pause, resume, purge or task listing through an API,
none of the Cloud Tasks v2 API beyond creating and deleting tasks, and no
tasks kept across a restart. The console can pause, resume and purge queues,
run, stop and delete tasks, and hold a scheduled task until its time, but
those are console controls, not an API.
- Cloud Functions: the functions your tasks run.
- Eventarc: custom events between functions.
- The console: queues and tasks as they run.