Xử lý các sự kiện trong vòng đời của tiện ích

Tiện ích của bạn có thể bao gồm các hàm Cloud Tasks sẽ kích hoạt khi một thực thể tiện ích trải qua bất kỳ sự kiện nào sau đây trong vòng đời:

  • Một phiên bản của tiện ích được cài đặt
  • Một phiên bản của tiện ích được cập nhật lên phiên bản mới
  • Cấu hình của một thực thể tiện ích bị thay đổi

Một trong những trường hợp sử dụng quan trọng nhất của tính năng này là điền dữ liệu cũ. Ví dụ: giả sử bạn đang tạo một tiện ích tạo bản xem trước hình thu nhỏ của hình ảnh được tải lên một vùng chứa Cloud Storage. Công việc chính của tiện ích sẽ được thực hiện trong một hàm do sự kiện onFinalize Cloud Storage kích hoạt. Tuy nhiên, chỉ những hình ảnh được tải lên sau khi tiện ích được cài đặt mới được xử lý. Bằng cách thêm vào tiện ích một hàm được kích hoạt bởi sự kiện vòng đời onInstall, bạn cũng có thể tạo bản xem trước hình thu nhỏ của mọi hình ảnh hiện có khi tiện ích được cài đặt.

Sau đây là một số trường hợp sử dụng khác của trình kích hoạt sự kiện trong vòng đời:

  • Tự động hoá quy trình thiết lập sau khi cài đặt (tạo bản ghi cơ sở dữ liệu, lập chỉ mục, v.v.)
  • Nếu bạn phải xuất bản các thay đổi không tương thích ngược, hãy tự động di chuyển dữ liệu khi cập nhật

Trình xử lý sự kiện trong vòng đời chạy trong thời gian ngắn

Nếu tác vụ của bạn có thể chạy hoàn toàn trong thời lượng Cloud Functions tối đa (9 phút khi dùng API thế hệ đầu tiên), bạn có thể viết trình xử lý sự kiện vòng đời dưới dạng một hàm duy nhất kích hoạt sự kiện onDispatch trên hàng đợi tác vụ:

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).
  });

Sau đó, trong tệp extension.yaml của tiện ích, hãy làm như sau:

  1. Đăng ký hàm của bạn làm tài nguyên tiện ích bằng bộ thuộc tính taskQueueTrigger. Nếu bạn đặt taskQueueTrigger thành bản đồ trống ({}), tiện ích của bạn sẽ cung cấp một hàng đợi Cloud Tasks bằng các chế độ cài đặt mặc định; bạn có thể tuỳ ý điều chỉnh các chế độ cài đặt này.

    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. Đăng ký hàm của bạn làm trình xử lý cho một hoặc nhiều sự kiện trong vòng đời:

    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
    
    

    Bạn có thể đăng ký các hàm cho bất kỳ sự kiện nào sau đây: onInstall, onUpdateonConfigure. Tất cả các sự kiện này đều không bắt buộc.

  3. Nên dùng: Nếu không cần thiết phải có tác vụ xử lý để tiện ích hoạt động, hãy thêm một tham số do người dùng định cấu hình cho phép người dùng chọn có bật tác vụ đó hay không.

    Ví dụ: hãy thêm một tham số như sau:

    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
    

    Và trong hàm của bạn, nếu tham số được đặt thành false, hãy thoát sớm:

    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.
        // ...
      });
    

Thực hiện các tác vụ chạy trong thời gian dài

Nếu tác vụ của bạn không thể hoàn thành trong thời lượng tối đa là Cloud Functions, hãy chia tác vụ thành các tác vụ phụ và thực hiện từng tác vụ phụ theo trình tự bằng cách xếp hàng các công việc bằng phương thức TaskQueue.enqueue() của Admin SDK.

Ví dụ: giả sử bạn muốn bổ sung dữ liệu Cloud Firestore. Bạn có thể chia bộ sưu tập tài liệu thành các khối bằng cách sử dụng con trỏ truy vấn. Sau khi xử lý một đoạn, hãy tăng độ lệch bắt đầu và đưa một lệnh gọi hàm khác vào hàng đợi như minh hoạ dưới đây:

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).
  }
});

Thêm hàm vào extension.yaml như mô tả trong mục trước.

Trạng thái báo cáo

Khi tất cả các hàm xử lý của bạn hoàn tất, dù thành công hay gặp lỗi, hãy báo cáo trạng thái của tác vụ bằng các phương thức thời gian chạy tiện ích của Admin SDK. Người dùng có thể xem trạng thái này trên trang chi tiết tiện ích trong bảng điều khiển Firebase.

Hoàn tất thành công và lỗi không nghiêm trọng

Để báo cáo việc hoàn tất thành công và các lỗi không nghiêm trọng (những lỗi không khiến tiện ích chuyển sang trạng thái không hoạt động), hãy sử dụng phương thức thời gian chạy tiện ích setProcessingState() của Admin SDK:

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

// ...

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

Bạn có thể đặt các trạng thái sau:

Trạng thái không nghiêm trọng
PROCESSING_COMPLETE

Dùng để báo cáo việc hoàn thành thành công một tác vụ. Ví dụ:

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

Dùng để báo cáo thành công một phần. Ví dụ:

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

Dùng để báo cáo các lỗi khiến nhiệm vụ không hoàn thành được, nhưng không khiến tiện ích không dùng được. Ví dụ:

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

Để báo cáo các lỗi không khiến tiện ích không dùng được, hãy gọi setFatalError().

NONE

Dùng để xoá trạng thái của việc cần làm. Bạn có thể tuỳ ý sử dụng phương thức này để xoá thông báo trạng thái khỏi bảng điều khiển (ví dụ: sau một khoảng thời gian kể từ khi đặt PROCESSING_COMPLETE). Ví dụ:

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

Lỗi nghiêm trọng

Nếu xảy ra lỗi khiến tiện ích không hoạt động được (ví dụ: một tác vụ thiết lập bắt buộc không thành công), hãy báo cáo lỗi nghiêm trọng bằng setFatalError():

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

// ...

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

Điều chỉnh hàng đợi tác vụ

Nếu bạn đặt thuộc tính taskQueueTrigger thành {}, tiện ích của bạn sẽ cung cấp một hàng đợi Cloud Tasks với chế độ cài đặt mặc định khi một phiên bản tiện ích được cài đặt. Ngoài ra, bạn có thể điều chỉnh giới hạn đồng thời của hàng đợi tác vụ và hành vi thử lại bằng cách cung cấp các giá trị cụ thể:

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

Hãy xem phần Định cấu hình hàng đợi Cloud Tasks trong tài liệu của Google Cloud để biết thông tin chi tiết về các thông số này.

Đừng cố gắng chỉ định các tham số hàng đợi tác vụ bằng cách truyền chúng đến taskQueue(). Các chế độ cài đặt này sẽ bị bỏ qua để ưu tiên cấu hình trong extension.yaml và cấu hình mặc định.

Ví dụ: mã này sẽ không hoạt động:

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(
    // ...
  );

Thuộc tính taskQueueTrigger trong extension.yaml là cách duy nhất để định cấu hình hàng đợi tác vụ của tiện ích.

Ví dụ

Tiện ích storage-resize-images, firestore-bigquery-exportfirestore-translate-text chính thức đều sử dụng trình xử lý sự kiện trong vòng đời để bổ sung dữ liệu.