āĻ•ā§āϞāĻžāωāĻĄ āϟāĻžāĻ¸ā§āϕ⧇āϰ āϏāĻžāĻĨ⧇ āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āĻĢāĻžāĻ‚āĻļāύ

āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ Google Cloud Tasks āϏ⧁āĻŦāĻŋāϧāĻž āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇ āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻĒāϕ⧇ āφāĻĒāύāĻžāϰ āĻĒā§āϰāϧāĻžāύ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ āĻĒā§āϰāĻŦāĻžāĻšā§‡āϰ āĻŦāĻžāχāϰ⧇ āĻ…ā§āϝāĻžāϏāĻŋāĻ™ā§āĻ•ā§āϰ⧋āύāĻžāϏāĻ­āĻžāĻŦ⧇ āϏāĻŽāϝāĻŧ-āϏāĻžāĻĒ⧇āĻ•ā§āώ, āϏāĻ‚āĻ¸ā§āĻĨāĻžāύ-āύāĻŋāĻŦāĻŋāĻĄāĻŧ āĻŦāĻž āĻŦā§āϝāĻžāĻ¨ā§āĻĄāωāχāĻĨ-āϏ⧀āĻŽāĻŋāϤ āĻ•āĻžāϜāϗ⧁āϞāĻŋ āϚāĻžāϞāĻžāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇⧎

āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āĻ•āĻ˛ā§āĻĒāύāĻž āĻ•āϰ⧁āύ āϝ⧇ āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āϰ⧇āϟ āϏ⧀āĻŽāĻž āϏāĻš āĻāĻ•āϟāĻŋ API āĻ āĻšā§‹āĻ¸ā§āϟ āĻ•āϰāĻž āϚāĻŋāĻ¤ā§āϰ āĻĢāĻžāχāϞāϗ⧁āϞāĻŋāϰ āĻāĻ•āϟāĻŋ āĻŦāĻĄāĻŧ āϏ⧇āĻŸā§‡āϰ āĻŦā§āϝāĻžāĻ•āφāĻĒ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āϚāĻžāύ⧎ āϏ⧇āχ API-āĻāϰ āĻāĻ•āϜāύ āĻĻāĻžāϝāĻŧāĻŋāĻ¤ā§āĻŦāĻļā§€āϞ āĻ­ā§‹āĻ•ā§āϤāĻž āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ, āφāĻĒāύāĻžāϕ⧇ āϤāĻžāĻĻ⧇āϰ āĻšāĻžāϰ⧇āϰ āϏ⧀āĻŽāĻžāϕ⧇ āϏāĻŽā§āĻŽāĻžāύ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤ āĻāĻ›āĻžāĻĄāĻŧāĻžāĻ“, āĻāχ āϧāϰāύ⧇āϰ āĻĻā§€āĻ°ā§āϘāĻŽā§‡āϝāĻŧāĻžāĻĻā§€ āĻ•āĻžāϜ āϟāĻžāχāĻŽāφāωāϟ āĻāĻŦāĻ‚ āĻŽā§‡āĻŽāϰāĻŋ āϏ⧀āĻŽāĻžāϰ āĻ•āĻžāϰāϪ⧇ āĻŦā§āϝāĻ°ā§āĻĨāϤāĻžāϰ āϜāĻ¨ā§āϝ āĻā§āρāĻ•āĻŋāĻĒā§‚āĻ°ā§āĻŖ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

āĻāχ āϜāϟāĻŋāϞāϤāĻž āĻĒā§āϰāĻļāĻŽāĻŋāϤ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ, āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āϞāĻŋāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύ āϝāĻž scheduleTime , āĻāĻŦāĻ‚ dispatchDeadline āĻŽāϤ⧋ āĻŽā§ŒāϞāĻŋāĻ• āϟāĻžāĻ¸ā§āĻ• āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ āϏ⧇āϟ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ⧇ Cloud Tasks āĻāĻ•āϟāĻŋ āϏāĻžāϰāĻŋāϤ⧇ āĻĢāĻžāĻ‚āĻļāύāϟāĻŋ āĻšāĻ¸ā§āϤāĻžāĻ¨ā§āϤāϰ āĻ•āϰ⧇⧎ Cloud Tasks āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻŦāĻŋāĻļ⧇āώāĻ­āĻžāĻŦ⧇ āĻĄāĻŋāϜāĻžāχāύ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āĻ•āĻžāĻ°ā§āϝāĻ•āϰ āĻ•āύāĻœā§‡āĻļāύ āĻ•āĻ¨ā§āĻŸā§āϰ⧋āϞ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻŦāĻ‚ āĻāχ āϧāϰāύ⧇āϰ āĻ•ā§āϰāĻŋāϝāĻŧāĻžāĻ•āϞāĻžāĻĒāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻžāϰ āύ⧀āϤāĻŋāϗ⧁āϞāĻŋ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ⧎

Cloud Functions for Firebase āϜāĻ¨ā§āϝ Firebase SDK āĻāĻŦāĻ‚ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ Firebase Admin SDK v10.2.0 āĻāĻŦāĻ‚ āωāĻšā§āϚāϤāϰ āĻāϰ āϏāĻžāĻĨ⧇ āχāĻ¨ā§āϟāĻžāϰāĻ…āĻĒāĻžāϰ⧇āϟāĻŋāĻ‚ āĻ•āϰ⧇āĨ¤

āĻĢāĻžāϝāĻŧāĻžāϰāĻŦ⧇āϏ⧇āϰ āϏāĻžāĻĨ⧇ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ Cloud Tasks āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāĻ•āϰāϪ⧇āϰ āϜāĻ¨ā§āϝ āϚāĻžāĻ°ā§āϜ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āφāϰāĻ“ āϤāĻĨā§āϝ⧇āϰ āϜāĻ¨ā§āϝ Cloud Tasks āĻŽā§‚āĻ˛ā§āϝ āĻĻ⧇āϖ⧁āύāĨ¤

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇, āĻāχ āĻ“āϝāĻŧāĻžāĻ°ā§āĻ•āĻĢā§āϞ⧋ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧁āύ:

  1. Cloud Functions āϜāĻ¨ā§āϝ Firebase SDK āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āϞāĻŋāϖ⧁āύāĨ¤
  2. āĻāĻ•āϟāĻŋ HTTP āĻ…āύ⧁āϰ⧋āϧ⧇āϰ āϏāĻžāĻĨ⧇ āĻāϟāĻŋ āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰ⧇ āφāĻĒāύāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰ⧁āύāĨ¤
  3. Firebase CLI āĻāϰ āϏāĻžāĻĨ⧇ āφāĻĒāύāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύāĨ¤ āĻĒā§āϰāĻĨāĻŽāĻŦāĻžāϰ āφāĻĒāύāĻžāϰ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, CLI āφāĻĒāύāĻžāϰ āϏ⧋āĻ°ā§āϏ āϕ⧋āĻĄā§‡ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ (āϰ⧇āϟ āϏ⧀āĻŽāĻŋāϤ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž) āϏāĻš Cloud Tasks āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ⧇āĨ¤
  4. āϏāĻĻā§āϝ āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋāϤ⧇ āĻ•āĻžāϜāϗ⧁āϞāĻŋ āϝ⧋āĻ— āĻ•āϰ⧁āύ, āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧇ āĻāĻ•āϟāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύ⧇āϰ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€ āϏ⧇āϟ āφāĻĒ āĻ•āϰāϤ⧇ āĻĒāϰāĻžāĻŽāĻŋāϤāĻŋāϗ⧁āϞāĻŋ āĻŦāϰāĻžāĻŦāϰ āĻĒāĻžāϏ āĻ•āϰ⧁āύ⧎ āφāĻĒāύāĻŋ Admin SDK āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϕ⧋āĻĄ āϞāĻŋāϖ⧇ āĻāĻŦāĻ‚ Cloud Functions for Firebase āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧇ āĻāϟāĻŋ āĻ…āĻ°ā§āϜāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āϞāĻŋāϖ⧁āύ

āĻāχ āĻŦāĻŋāĻ­āĻžāϗ⧇ āϕ⧋āĻĄ āύāĻŽā§āύāĻžāϗ⧁āϞāĻŋ āĻāĻŽāύ āĻāĻ•āϟāĻŋ āĻ…ā§āϝāĻžāĻĒ⧇āϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āϝāĻž āĻāĻ•āϟāĻŋ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āϏ⧇āϟ āφāĻĒ āĻ•āϰ⧇ āϝāĻž NASA-āĻāϰ Astronomy Picture of the Day āĻĨ⧇āϕ⧇ āϏāĻŽāĻ¸ā§āϤ āĻ›āĻŦāĻŋ āĻŦā§āϝāĻžāĻ• āφāĻĒ āĻ•āϰ⧇⧎ āĻļ⧁āϰ⧁ āĻ•āϰāϤ⧇, āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āĻŽāĻĄāĻŋāωāϞ āφāĻŽāĻĻāĻžāύāĻŋ āĻ•āϰ⧁āύ:

Node.js

// Dependencies for task queue functions.
const {onTaskDispatched} = require("firebase-functions/v2/tasks");
const {onRequest, HttpsError} = require("firebase-functions/v2/https");
const {getFunctions} = require("firebase-admin/functions");
const {logger} = require("firebase-functions/v2");

// Dependencies for image backup.
const path = require("path");
const fetch = require("node-fetch");
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
const {GoogleAuth} = require("google-auth-library");

āĻĒāĻžāχāĻĨāύ

# Dependencies for task queue functions.
from google.cloud import tasks_v2
import requests
from firebase_functions.options import RetryConfig, RateLimits, SupportedRegion

# Dependencies for image backup.
from datetime import datetime, timedelta
import json
import pathlib
from urllib.parse import urlparse
from firebase_admin import initialize_app, storage, functions
from firebase_functions import https_fn, tasks_fn, params
import google.auth
from google.auth.transport.requests import AuthorizedSession

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āϜāĻ¨ā§āϝ onTaskDispatched āĻŦāĻž on_task_dispatched āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύāĨ¤ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āϞ⧇āĻ–āĻžāϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ āĻĒā§āϰāϤāĻŋ-āϏāĻžāϰāĻŋ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻāĻŦāĻ‚ āϰ⧇āϟ-āϏ⧀āĻŽāĻŋāϤ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰ⧁āύ

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ āϏ⧁āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟāĻ­āĻžāĻŦ⧇ āĻšāĻžāϰ⧇āϰ āϏ⧀āĻŽāĻž āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋāϰ āφāϚāϰāĻŖ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ āϏ⧇āϟāĻŋāĻ‚āϏ⧇āϰ āĻāĻ•āϟāĻŋ āĻļāĻ•ā§āϤāĻŋāĻļāĻžāϞ⧀ āϏ⧇āĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āφāϏ⧇:

Node.js

exports.backupapod = onTaskDispatched(
    {
      retryConfig: {
        maxAttempts: 5,
        minBackoffSeconds: 60,
      },
      rateLimits: {
        maxConcurrentDispatches: 6,
      },
    }, async (req) => {

āĻĒāĻžāχāĻĨāύ

@tasks_fn.on_task_dispatched(retry_config=RetryConfig(max_attempts=5, min_backoff_seconds=60),
                             rate_limits=RateLimits(max_concurrent_dispatches=10))
def backupapod(req: tasks_fn.CallableRequest) -> str:
    """Grabs Astronomy Photo of the Day (APOD) using NASA's API."""
  • retryConfig.maxAttempts=5 : āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋāϤ⧇ āĻĨāĻžāĻ•āĻž āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻ•āĻžāϜ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ 5 āĻŦāĻžāϰ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϟāĻŋ āύ⧇āϟāĻ“āϝāĻŧāĻžāĻ°ā§āĻ• āĻ¤ā§āϰ⧁āϟāĻŋ āĻŦāĻž āύāĻŋāĻ°ā§āĻ­āϰāĻļā§€āϞ, āĻŦāĻžāĻšā§āϝāĻŋāĻ• āĻĒāϰāĻŋāώ⧇āĻŦāĻžāϰ āĻ…āĻ¸ā§āĻĨāĻžāϝāĻŧā§€ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻŦā§āϝāĻžāĻšāϤ⧇āϰ āĻŽāϤ⧋ āĻ•ā§āώāĻŖāĻ¸ā§āĻĨāĻžāϝāĻŧā§€ āĻ¤ā§āϰ⧁āϟāĻŋāϗ⧁āϞāĻŋ āĻĒā§āϰāĻļāĻŽāĻŋāϤ āĻ•āϰāϤ⧇ āϏāĻšāĻžāϝāĻŧāϤāĻž āĻ•āϰ⧇⧎

  • retryConfig.minBackoffSeconds=60 : āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻ•āĻžāϜ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĒā§āϰāĻšā§‡āĻˇā§āϟāĻž āĻĨ⧇āϕ⧇ āĻ•āĻŽāĻĒāĻ•ā§āώ⧇ 60 āϏ⧇āϕ⧇āĻ¨ā§āĻĄā§‡āϰ āĻŽāĻ§ā§āϝ⧇ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϟāĻŋ āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻĒā§āϰāĻšā§‡āĻˇā§āϟāĻžāϰ āĻŽāĻ§ā§āϝ⧇ āĻāĻ•āϟāĻŋ āĻŦāĻĄāĻŧ āĻŦāĻžāĻĢāĻžāϰ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇ āϤāĻžāχ āφāĻŽāϰāĻž āϖ⧁āĻŦ āĻĻā§āϰ⧁āϤ 5āϟāĻŋ āĻĒ⧁āύāσāĻĒā§āϰāĻšā§‡āĻˇā§āϟāĻž āĻļ⧇āώ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϤāĻžāĻĄāĻŧāĻžāĻšā§āĻĄāĻŧā§‹ āĻ•āϰāĻŋ āύāĻžāĨ¤

  • rateLimits.maxConcurrentDispatch=6 : āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ⧇ āϏāĻ°ā§āĻŦāĻžāϧāĻŋāĻ• 6āϟāĻŋ āĻ•āĻžāϜ āĻĒāĻžāĻ āĻžāύ⧋ āĻšāϝāĻŧāĨ¤ āĻāϟāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻšāĻŋāϤ āĻĢāĻžāĻ‚āĻļāύ⧇ āĻ…āύ⧁āϰ⧋āϧ⧇āϰ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĨāĻŋāϰ āĻĒā§āϰāĻŦāĻžāĻš āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϏāĻ•ā§āϰāĻŋāϝāĻŧ āĻĻ⧃āĻˇā§āϟāĻžāĻ¨ā§āϤ āĻāĻŦāĻ‚ āĻ āĻžāĻ¨ā§āĻĄāĻž āĻļ⧁āϰ⧁āϰ āϏāĻ‚āĻ–ā§āϝāĻž āĻ•āĻŽāĻžāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤

āĻŸā§‡āĻ¸ā§āϟ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ

āĻŦ⧇āĻļāĻŋāϰāĻ­āĻžāĻ— āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇, Cloud Functions āĻāĻŽā§āϞ⧇āϟāϰ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāĻžāϰ āϏāĻ°ā§āĻŦā§‹āĻ¤ā§āϤāĻŽ āωāĻĒāĻžāϝāĻŧāĨ¤ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āχāĻŽā§āϞ⧇āĻļāύ⧇āϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻĒāϕ⧇ āϕ⧀āĻ­āĻžāĻŦ⧇ āωāĻĒāĻ•āϰāĻŖ āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ⧇āύ āϤāĻž āĻļāĻŋāĻ–āϤ⧇ āĻāĻŽā§āϞ⧇āϟāϰ āĻ¸ā§āϝ⧁āϟ āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύ āĻĻ⧇āϖ⧁āύāĨ¤

āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤāĻ­āĻžāĻŦ⧇, āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ Firebase Local Emulator Suite āϏāĻžāϧāĻžāϰāĻŖ HTTP āĻĢāĻžāĻ‚āĻļāύ āĻšāĻŋāϏāĻžāĻŦ⧇ āωāĻ¨ā§āĻŽā§āĻ•ā§āϤ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ JSON āĻĄā§‡āϟāĻž āĻĒ⧇āϞ⧋āĻĄ āϏāĻš āĻāĻ•āϟāĻŋ HTTP POST āĻ…āύ⧁āϰ⧋āϧ āĻĒāĻžāĻ āĻŋāϝāĻŧ⧇ āĻāĻ•āϟāĻŋ āĻ…āύ⧁āĻ•āϰāĻŖ āĻ•āϰāĻž āϟāĻžāĻ¸ā§āĻ• āĻĢāĻžāĻ‚āĻļāύ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:

 # start the Local Emulator Suite
 firebase emulators:start

 # trigger the emulated task queue function
 curl \
  -X POST                                            # An HTTP POST request...
  -H "content-type: application/json" \              # ... with a JSON body
  http://localhost:$PORT/$PROJECT_ID/$REGION/$NAME \ # ... to function url
  -d '{"data": { ... some data .... }}'              # ... with JSON encoded data

āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ

Firebase CLI āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰ⧁āύ:

$ firebase deploy --only functions:backupapod

āĻĒā§āϰāĻĨāĻŽāĻŦāĻžāϰ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, CLI āφāĻĒāύāĻžāϰ āϏ⧋āĻ°ā§āϏ āϕ⧋āĻĄā§‡ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ (āϰ⧇āϟ āϏ⧀āĻŽāĻŋāϤ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž) āϏāĻš Cloud Tasks āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āϤ⧈āϰāĻŋ āĻ•āϰ⧇āĨ¤

āĻĢāĻžāĻ‚āĻļāύ āĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻ…āύ⧁āĻŽāϤāĻŋ āĻ¤ā§āϰ⧁āϟāĻŋāϰ āϏāĻŽā§āĻŽā§āĻ–ā§€āύ āĻšāύ, āϤāĻžāĻšāϞ⧇ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϝ⧇ āϝāĻĨāĻžāϝāĻĨ IAM āĻ­ā§‚āĻŽāĻŋāĻ•āĻžāϗ⧁āϞāĻŋ āĻ¸ā§āĻĨāĻžāĻĒāύāĻžāϰ āĻ•āĻŽāĻžāĻ¨ā§āĻĄ āϚāĻžāϞāĻžāĻšā§āϛ⧇āύ āĻāĻŽāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϕ⧇ āĻŦāϰāĻžāĻĻā§āĻĻ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤

āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ

āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ Cloud Tasks āĻāĻ•āϟāĻŋ āĻŦāĻŋāĻļā§āĻŦāĻ¸ā§āϤ āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻĒāϰāĻŋāĻŦ⧇āĻļ āĻĨ⧇āϕ⧇ āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āϝ⧇āĻŽāύ Cloud Functions for Firebase Node.js-āĻāϰ āϜāĻ¨ā§āϝ Firebase Admin SDK āĻŦāĻž Python-āĻāϰ āϜāĻ¨ā§āϝ Google āĻ•ā§āϞāĻžāωāĻĄ āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇⧎ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ Admin SDK āĻ āύāϤ⧁āύ āĻšāύ, āĻļ⧁āϰ⧁ āĻ•āϰāϤ⧇ āĻāĻ•āϟāĻŋ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇ Firebase āϝ⧋āĻ— āĻ•āϰ⧁āύ āĻĻ⧇āϖ⧁āύāĨ¤

āĻāĻ•āϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ āĻĒā§āϰāĻŦāĻžāĻš āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āϟāĻžāĻ¸ā§āĻ• āϤ⧈āϰāĻŋ āĻ•āϰ⧇, āĻāϟāĻŋāϕ⧇ Cloud Tasks āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϟāĻžāĻ¸ā§āϕ⧇āϰ āϜāĻ¨ā§āϝ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ āϏ⧇āϟ āĻ•āϰ⧇:

Node.js

exports.enqueuebackuptasks = onRequest(
    async (_request, response) => {
      const queue = getFunctions().taskQueue("backupapod");
      const targetUri = await getFunctionUrl("backupapod");

      const enqueues = [];
      for (let i = 0; i <= BACKUP_COUNT; i += 1) {
        const iteration = Math.floor(i / HOURLY_BATCH_SIZE);
        // Delay each batch by N * hour
        const scheduleDelaySeconds = iteration * (60 * 60);

        const backupDate = new Date(BACKUP_START_DATE);
        backupDate.setDate(BACKUP_START_DATE.getDate() + i);
        // Extract just the date portion (YYYY-MM-DD) as string.
        const date = backupDate.toISOString().substring(0, 10);
        enqueues.push(
            queue.enqueue({date}, {
              scheduleDelaySeconds,
              dispatchDeadlineSeconds: 60 * 5, // 5 minutes
              uri: targetUri,
            }),
        );
      }
      await Promise.all(enqueues);
      response.sendStatus(200);
    });

āĻĒāĻžāχāĻĨāύ

@https_fn.on_request()
def enqueuebackuptasks(_: https_fn.Request) -> https_fn.Response:
    """Adds backup tasks to a Cloud Tasks queue."""
    task_queue = functions.task_queue("backupapod")
    target_uri = get_function_url("backupapod")

    for i in range(BACKUP_COUNT):
        batch = i // HOURLY_BATCH_SIZE

        # Delay each batch by N hours
        schedule_delay = timedelta(hours=batch)
        schedule_time = datetime.now() + schedule_delay

        dispatch_deadline_seconds = 60 * 5  # 5 minutes

        backup_date = BACKUP_START_DATE + timedelta(days=i)
        body = {"data": {"date": backup_date.isoformat()[:10]}}
        task_options = functions.TaskOptions(schedule_time=schedule_time,
                                             dispatch_deadline_seconds=dispatch_deadline_seconds,
                                             uri=target_uri)
        task_queue.enqueue(body, task_options)
    return https_fn.Response(status=200, response=f"Enqueued {BACKUP_COUNT} tasks")
  • āύāĻŽā§āύāĻž āϕ⧋āĻĄāϟāĻŋ Nth āϟāĻžāĻ¸ā§āϕ⧇āϰ āϜāĻ¨ā§āϝ Nth āĻŽāĻŋāύāĻŋāĻŸā§‡āϰ āĻŦāĻŋāϞāĻŽā§āĻŦ āϝ⧁āĻ•ā§āϤ āĻ•āϰ⧇ āĻ•āĻžāĻ°ā§āϝ āϏāĻŽā§āĻĒāĻžāĻĻāύāϕ⧇ āĻ›āĻĄāĻŧāĻŋāϝāĻŧ⧇ āĻĻ⧇āĻ“āϝāĻŧāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰ⧇āĨ¤ āĻāϟāĻŋ āĻŸā§āϰāĻŋāĻ—āĻžāϰāĻŋāĻ‚ ~ 1 āϟāĻžāĻ¸ā§āĻ•/āĻŽāĻŋāύāĻŋāϟ āĻ…āύ⧁āĻŦāĻžāĻĻ āĻ•āϰ⧇⧎ āĻŽāύ⧇ āϰāĻžāĻ–āĻŦ⧇āύ āϝ⧇ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ Cloud Tasks āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϏāĻŽāϝāĻŧ⧇ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āĻŸā§āϰāĻŋāĻ—āĻžāϰ āĻ•āϰāϤ⧇ āϚāĻžāύ āϤāĻŦ⧇ āφāĻĒāύāĻŋ scheduleTime (Node.js) āĻŦāĻž schedule_time (Python) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

  • āύāĻŽā§āύāĻž āϕ⧋āĻĄāϟāĻŋ Cloud Tasks āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āĻ• āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āĻ•āϤ āϏāĻŽāϝāĻŧ āĻ…āĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻŦ⧇ āϤāĻž āϏ⧇āϟ āĻ•āϰ⧇āĨ¤ Cloud Tasks āϏāĻžāϰāĻŋāϰ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ⧇āϰ āĻĒāϰ⧇ āĻŦāĻž āĻāχ āϏāĻŽāϝāĻŧāϏ⧀āĻŽāĻžāϝāĻŧ āύāĻž āĻĒ⧌āρāĻ›āĻžāύ⧋ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϟāĻžāĻ¸ā§āĻ•āϟāĻŋ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻŦ⧇āĨ¤ āύāĻŽā§āύāĻžāϝāĻŧ, āϏāĻžāϰāĻŋāϟāĻŋ 5 āĻŦāĻžāϰ āĻĒāĻ°ā§āϝāĻ¨ā§āϤ āϟāĻžāĻ¸ā§āĻ•āϟāĻŋ āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇, āϤāĻŦ⧇ āĻĒ⧁āϰ⧋ āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϟāĻŋ (āĻĒ⧁āύāϰāĻžāϝāĻŧ āĻšā§‡āĻˇā§āϟāĻž āϏāĻš) 5 āĻŽāĻŋāύāĻŋāĻŸā§‡āϰ āĻŦ⧇āĻļāĻŋ āϏāĻŽāϝāĻŧ āϞāĻžāĻ—āϞ⧇ āϟāĻžāĻ¸ā§āĻ•āϟāĻŋ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻŦāĻžāϤāĻŋāϞ āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧāĨ¤

āϏāĻŽāĻ¸ā§āϝāĻž āϏāĻŽāĻžāϧāĻžāύ

Cloud Tasks āϞāĻ—āĻŋāĻ‚ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ

Cloud Tasks āϞāĻ—āϗ⧁āϞāĻŋāϤ⧇ āĻāĻ•āϟāĻŋ āϟāĻžāĻ¸ā§āϕ⧇āϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āĻ…āύ⧁āϰ⧋āϧ⧇āϰ āĻ¸ā§āĻĨāĻŋāϤāĻŋāϰ āĻŽāϤ⧋ āĻĻāϰāĻ•āĻžāϰ⧀ āĻĄāĻžāϝāĻŧāĻ—āύāĻŋāĻ¸ā§āϟāĻŋāĻ• āϤāĻĨā§āϝ āĻĨāĻžāϕ⧇āĨ¤ āĻĄāĻŋāĻĢāĻ˛ā§āϟāϰ⧂āĻĒ⧇, Cloud Tasks āĻĨ⧇āϕ⧇ āϞāĻ—āϗ⧁āϞāĻŋ āĻŦāĻ¨ā§āϧ āĻšāϝāĻŧ⧇ āϝāĻžāϝāĻŧ āĻ•āĻžāϰāĻŖ āĻāϟāĻŋ āφāĻĒāύāĻžāϰ āĻĒā§āϰ⧋āĻœā§‡āĻ•ā§āĻŸā§‡ āĻĒā§āϰāϚ⧁āϰ āĻĒāϰāĻŋāĻŽāĻžāϪ⧇ āϞāĻ— āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇⧎ āφāĻĒāύāĻŋ āϝāĻ–āύ āφāĻĒāύāĻžāϰ āϟāĻžāĻ¸ā§āĻ• āϏāĻžāϰāĻŋ āĻĢāĻžāĻ‚āĻļāύ āϏāĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻŦāĻŋāĻ•āĻžāĻļ āĻāĻŦāĻ‚ āĻĄāĻŋāĻŦāĻžāĻ— āĻ•āϰāϛ⧇āύ āϤāĻ–āύ āφāĻŽāϰāĻž āφāĻĒāύāĻžāϕ⧇ āĻĄāĻŋāĻŦāĻžāĻ— āϞāĻ— āϚāĻžāϞ⧁ āĻ•āϰāĻžāϰ āĻĒāϰāĻžāĻŽāĻ°ā§āĻļ āĻĻāĻŋāχāĨ¤ āϞāĻ—āĻŋāĻ‚ āϚāĻžāϞ⧁ āĻ•āϰāĻž āĻĻ⧇āϖ⧁āύāĨ¤

āφāχāĻāĻāĻŽ āĻ…āύ⧁āĻŽāϤāĻŋ

āĻ•āĻžāϜāϗ⧁āϞāĻŋ āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻŦāĻž Cloud Tasks āφāĻĒāύāĻžāϰ āϟāĻžāĻ¸ā§āĻ• āĻ•āĻŋāω āĻĢāĻžāĻ‚āĻļāύāϗ⧁āϞāĻŋ āϚāĻžāϞ⧁ āĻ•āϰāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ PERMISSION DENIED āĻ¤ā§āϰ⧁āϟāĻŋ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύ⧎ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύ āϝ⧇ āφāĻĒāύāĻžāϰ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒ⧇ āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ IAM āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ āφāϛ⧇:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudtasks.enqueuer
  • Cloud Tasks āϟāĻžāĻ¸ā§āĻ•āϗ⧁āϞāĻŋ āϏāĻžāϰāĻŋāĻŦāĻĻā§āϧ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻĒāϰāĻŋāϚāϝāĻŧāϟāĻŋāϰ āϜāĻ¨ā§āϝ Cloud Tasks āϕ⧋āύāĻ“ āϟāĻžāĻ¸ā§āϕ⧇āϰ āϏāĻžāĻĨ⧇ āϝ⧁āĻ•ā§āϤ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻ…āύ⧁āĻŽāϤāĻŋ āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧎

    āύāĻŽā§āύāĻžāϝāĻŧ, āĻāϟāĻŋ App Engine āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĨ¤

App Engine āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āĻšāĻŋāϏāĻžāĻŦ⧇ App Engine āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĒāϰāĻŋāώ⧇āĻŦāĻž āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āϕ⧀āĻ­āĻžāĻŦ⧇ āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻŦ⧇āύ āϤāĻžāϰ āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻžāĻŦāϞ⧀āϰ āϜāĻ¨ā§āϝ Google āĻ•ā§āϞāĻžāωāĻĄ IAM āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āĻŸā§‡āĻļāύ āĻĻ⧇āϖ⧁āύāĨ¤

gcloud functions add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1 \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudfunctions.invoker