จัดการเหตุการณ์ในวงจรของส่วนขยาย

ส่วนขยายของคุณสามารถมีCloud Tasksฟังก์ชัน ที่ทริกเกอร์เมื่ออินสแตนซ์ของส่วนขยายผ่านเหตุการณ์ในวงจรต่อไปนี้

  • มีการติดตั้งอินสแตนซ์ของส่วนขยาย
  • มีการอัปเดตอินสแตนซ์ของส่วนขยายเป็นเวอร์ชันใหม่
  • มีการเปลี่ยนแปลงการกำหนดค่าของอินสแตนซ์ส่วนขยาย

กรณีการใช้งานที่สำคัญที่สุดอย่างหนึ่งของฟีเจอร์นี้คือการเติมข้อมูลย้อนหลัง สมมติว่าคุณกำลังสร้างส่วนขยายที่สร้างตัวอย่างภาพขนาดย่อของรูปภาพที่อัปโหลดไปยังบัคเก็ต Cloud Storage งานหลักของส่วนขยาย จะดำเนินการในฟังก์ชันที่ทริกเกอร์โดยเหตุการณ์ onFinalize Cloud Storage อย่างไรก็ตาม ระบบจะประมวลผลเฉพาะรูปภาพที่อัปโหลด หลังจาก ติดตั้งส่วนขยายแล้วเท่านั้น การรวมฟังก์ชันที่ทริกเกอร์โดยเหตุการณ์ในวงจร onInstall ไว้ในส่วนขยายจะช่วยให้คุณสร้างตัวอย่างภาพขนาดย่อของรูปภาพ ที่มีอยู่ ได้ด้วยเมื่อมีการติดตั้งส่วนขยาย

กรณีการใช้งานอื่นๆ ของทริกเกอร์เหตุการณ์ในวงจร ได้แก่

  • ตั้งค่าหลังการติดตั้งโดยอัตโนมัติ (สร้างบันทึกฐานข้อมูล การจัดทำดัชนี ฯลฯ)
  • หากคุณต้องเผยแพร่การเปลี่ยนแปลงที่เข้ากันไม่ได้กับเวอร์ชันก่อนหน้า ให้ย้ายข้อมูลโดยอัตโนมัติเมื่อมีการอัปเดต

เครื่องจัดการเหตุการณ์ในวงจรที่ทำงานสั้นๆ

หากงานของคุณทำงานเสร็จสมบูรณ์ได้ภายใน ระยะเวลาCloud Functionsสูงสุด (9 นาทีโดยใช้ API รุ่นแรก) คุณสามารถเขียนเครื่องจัดการเหตุการณ์ในวงจร เป็นฟังก์ชันเดียวที่ทริกเกอร์ในเหตุการณ์ onDispatch ของคิวงานได้

export const myTaskFunction = functions.tasks.taskQueue()
  .onDispatch(async () => {
    // Complete your lifecycle event handling task.
    // ...

    // When processing is complete, report status to the user (see below).
  });

จากนั้นให้ทำดังนี้ในไฟล์ extension.yaml ของส่วนขยาย

  1. ลงทะเบียนฟังก์ชันเป็นทรัพยากรส่วนขยายโดยตั้งค่าพร็อพเพอร์ตี้ taskQueueTrigger หากตั้งค่า taskQueueTrigger เป็นแผนที่ว่าง ({}) ส่วนขยาย จะจัดเตรียมคิว Cloud Tasks โดยใช้การตั้งค่าเริ่มต้น และคุณเลือกปรับการตั้งค่าเหล่านี้ได้

    resources:
      - name: myTaskFunction
        type: firebaseextensions.v1beta.function
        description: >-
          Describe the task performed when the function is triggered by a lifecycle
          event
        properties:
          location: ${LOCATION}
          taskQueueTrigger: {}
    
  2. ลงทะเบียนฟังก์ชันเป็นเครื่องจัดการสำหรับเหตุการณ์ในวงจรอย่างน้อย 1 เหตุการณ์

    resources:
      - ...
    lifecycleEvents:
      onInstall:
        function: myTaskFunction
        processingMessage: Resizing your existing images
      onUpdate:
        function: myOtherTaskFunction
        processingMessage: Setting up your extension
      onConfigure:
        function: myOtherTaskFunction
        processingMessage: Setting up your extension
    
    

    คุณสามารถลงทะเบียนฟังก์ชันสำหรับเหตุการณ์ต่อไปนี้ onInstall, onUpdate และ onConfigure เหตุการณ์ทั้งหมดนี้เป็นตัวเลือก

  3. แนะนำ: หากส่วนขยายไม่จำเป็นต้องมีงานประมวลผลเพื่อให้ ทำงานได้ ให้เพิ่มพารามิเตอร์ที่ผู้ใช้กำหนดค่าได้ ซึ่งช่วยให้ผู้ใช้เลือกว่าจะเปิดใช้หรือไม่

    ตัวอย่างเช่น เพิ่มพารามิเตอร์ดังต่อไปนี้

    params:
      - param: DO_BACKFILL
        label: Backfill existing images
        description: >
          Should existing, unresized images in the Storage bucket be resized as well?
        type: select
        options:
          - label: Yes
            value: true
          - label: No
            value: false
    

    และในฟังก์ชัน หากตั้งค่าพารามิเตอร์เป็น false ให้ออกจากฟังก์ชันก่อนกำหนด

    export const myTaskFunction = functions.tasks.taskQueue()
      .onDispatch(async () => {
        if (!process.env.DO_BACKFILL) {
          await runtime.setProcessingState(
            "PROCESSING_COMPLETE",
            "Existing images were not resized."
          );
          return;
        }
        // Complete your lifecycle event handling task.
        // ...
      });
    

การทำงานที่ใช้เวลานาน

หากงานไม่สามารถดำเนินการให้เสร็จสมบูรณ์ได้ภายในระยะเวลาสูงสุด Cloud Functions ให้แบ่งงานออกเป็นงานย่อยและทำงานย่อยแต่ละรายการตามลำดับโดยการจัดคิวงานด้วยเมธอด TaskQueue.enqueue() ของ Admin SDK

ตัวอย่างเช่น สมมติว่าคุณต้องการเติมข้อมูล Cloud Firestore ย้อนหลัง คุณสามารถ แยกคอลเล็กชันเอกสารออกเป็นส่วนๆ โดยใช้ เคอร์เซอร์การค้นหา. หลังจากประมวลผลส่วนหนึ่งแล้ว ให้เลื่อนออฟเซ็ตเริ่มต้นและจัดคิวการเรียกใช้ฟังก์ชันอื่นดังที่แสดงด้านล่าง

import { getFirestore } from "firebase-admin/firestore";
import { getFunctions } from "firebase-admin/functions";

exports.backfilldata = functions.tasks.taskQueue().onDispatch(async (data) => {
  // When a lifecycle event triggers this function, it doesn't pass any data,
  // so an undefined offset indicates we're on our first invocation and should
  // start at offset 0. On subsequent invocations, we'll pass an explicit
  // offset.
  const offset = data["offset"] ?? 0;

  // Get a batch of documents, beginning at the offset.
  const snapshot = await getFirestore()
    .collection(process.env.COLLECTION_PATH)
    .startAt(offset)
    .limit(DOCS_PER_BACKFILL)
    .get();
  // Process each document in the batch.
  const processed = await Promise.allSettled(
    snapshot.docs.map(async (documentSnapshot) => {
      // Perform the processing.
    })
  );

  // If we processed a full batch, there are probably more documents to
  // process, so enqueue another invocation of this function, specifying
  // the offset to start with.
  //
  // If we processed less than a full batch, we're done.
  if (processed.length == DOCS_PER_BACKFILL) {
    const queue = getFunctions().taskQueue(
      "backfilldata",
      process.env.EXT_INSTANCE_ID
    );
    await queue.enqueue({
      offset: offset + DOCS_PER_BACKFILL,
    });
  } else {
      // Processing is complete. Report status to the user (see below).
  }
});

เพิ่มฟังก์ชันลงใน extension.yaml ตามที่อธิบายไว้ใน ส่วนก่อนหน้า

สถานะการรายงาน

เมื่อฟังก์ชันการประมวลผลทั้งหมดทำงานเสร็จ ไม่ว่าจะสำเร็จหรือมีข้อผิดพลาด ให้รายงานสถานะของงานโดยใช้เมธอดรันไทม์ของส่วนขยาย Admin SDK ผู้ใช้จะเห็นสถานะนี้ในหน้ารายละเอียดส่วนขยายใน Firebase คอนโซล

การดำเนินการเสร็จสมบูรณ์และข้อผิดพลาดที่ไม่ร้ายแรง

หากต้องการรายงานการดำเนินการเสร็จสมบูรณ์และข้อผิดพลาดที่ไม่ร้ายแรง (ข้อผิดพลาดที่ไม่ได้ทำให้ส่วนขยายอยู่ในสถานะที่ไม่สามารถใช้งานได้) ให้ใช้เมธอดรันไทม์ของส่วนขยาย setProcessingState() ของ Admin SDK

import { getExtensions } from "firebase-admin/extensions";

// ...

getExtensions().runtime().setProcessingState(processingState, message);

คุณสามารถตั้งค่าสถานะต่อไปนี้

สถานะข้อผิดพลาดที่ไม่ร้ายแรง
PROCESSING_COMPLETE

ใช้เพื่อรายงานการทำงานของงานเสร็จสมบูรณ์ ตัวอย่าง:

getExtensions().runtime().setProcessingState(
  "PROCESSING_COMPLETE",
  `Backfill complete. Successfully processed ${numSuccess} documents.`
);
PROCESSING_WARNING

ใช้เพื่อรายงานความสำเร็จบางส่วน ตัวอย่าง:

getExtensions().runtime().setProcessingState(
  "PROCESSING_WARNING",
  `Backfill complete. ${numSuccess} documents processed successfully.`
    + ` ${numFailed} documents failed to process. ${listOfErrors}.`
    + ` ${instructionsToFixTheProblem}`
);
PROCESSING_FAILED

ใช้เพื่อรายงานข้อผิดพลาดที่ทำให้งานไม่เสร็จสมบูรณ์ แต่ไม่ได้ทำให้ส่วนขยายใช้งานไม่ได้ ตัวอย่าง:

getExtensions().runtime().setProcessingState(
  "PROCESSING_FAILED",
  `Backfill failed. ${errorMsg} ${optionalInstructionsToFixTheProblem}.`
);

หากต้องการรายงานข้อผิดพลาดที่ ทำให้ส่วนขยายใช้งานไม่ได้ ให้เรียกใช้ setFatalError()

NONE

ใช้เพื่อล้างสถานะของงาน คุณสามารถใช้ตัวเลือกนี้เพื่อล้างข้อความสถานะจากคอนโซลได้ (เช่น หลังจากผ่านไประยะหนึ่งนับตั้งแต่ตั้งค่า PROCESSING_COMPLETE) ตัวอย่าง:

getExtensions().runtime().setProcessingState("NONE");

ข้อผิดพลาดร้ายแรง

หากเกิดข้อผิดพลาดที่ทำให้ส่วนขยายทำงานไม่ได้ เช่น งานตั้งค่าที่จำเป็นล้มเหลว ให้รายงานข้อผิดพลาดร้ายแรงด้วย setFatalError()

import { getExtensions } from "firebase-admin/extensions";

// ...

getExtensions().runtime().setFatalError(`Post-installation setup failed. ${errorMessage}`);

การปรับคิวงาน

หากตั้งค่าพร็อพเพอร์ตี้ taskQueueTrigger เป็น {} ส่วนขยายจะจัดเตรียมคิว Cloud Tasks ด้วยการตั้งค่าเริ่มต้นเมื่อมีการติดตั้งอินสแตนซ์ของส่วนขยาย หรือคุณจะปรับขีดจำกัดการทำงานพร้อมกันและลักษณะการทำงานในการลองใหม่ของคิวงานได้โดยระบุค่าที่ต้องการ

resources:
  - name: myTaskFunction
    type: firebaseextensions.v1beta.function
    description: >-
      Perform a task when triggered by a lifecycle event
    properties:
      location: ${LOCATION}
      taskQueueTrigger:
        rateLimits:
          maxConcurrentDispatches: 1000
          maxDispatchesPerSecond: 500
        retryConfig:
          maxAttempts: 100  # Warning: setting this too low can prevent the function from running
          minBackoffSeconds: 0.1
          maxBackoffSeconds: 3600
          maxDoublings: 16
lifecycleEvents:
  onInstall: 
    function: myTaskFunction
    processingMessage: Resizing your existing images
  onUpdate:
    function: myTaskFunction
    processingMessage: Setting up your extension
  onConfigure:
    function: myOtherTaskFunction
    processingMessage: Setting up your extension

ดูรายละเอียดเกี่ยวกับพารามิเตอร์เหล่านี้ได้ที่หัวข้อกำหนดค่าคิว Cloud Tasks ในเอกสาร Google Cloud

อย่าพยายามระบุพารามิเตอร์คิวงานโดยส่งพารามิเตอร์ไปยัง taskQueue() ระบบจะละเว้นการตั้งค่าเหล่านี้และใช้การกำหนดค่าใน extension.yaml และค่าเริ่มต้นของการกำหนดค่าแทน

ตัวอย่างเช่น การดำเนินการต่อไปนี้จะไม่ได้ผล

export const myBrokenTaskFunction = functions.tasks
  // DON'T DO THIS IN AN EXTENSION! THESE SETTINGS ARE IGNORED.
  .taskQueue({
    retryConfig: {
      maxAttempts: 5,
      minBackoffSeconds: 60,
    },
    rateLimits: {
      maxConcurrentDispatches: 1000,
      maxDispatchesPerSecond: 10,
    },
  })
  .onDispatch(
    // ...
  );

พร็อพเพอร์ตี้ taskQueueTrigger ใน extension.yaml เป็นวิธีเดียวในการกำหนดค่าคิวงานของส่วนขยาย

ตัวอย่าง

ส่วนขยาย storage-resize-images, firestore-bigquery-export, และ firestore-translate-text อย่างเป็นทางการทั้งหมดใช้เครื่องจัดการเหตุการณ์ในวงจรเพื่อเติมข้อมูลย้อนหลัง