확장 프로그램에는 확장 프로그램 인스턴스에 다음과 같은 수명 주기 이벤트가 진행될 때 트리거되는 Cloud Tasks 함수가 포함될 수 있습니다.
- 확장 프로그램 인스턴스가 설치됨
- 확장 프로그램 인스턴스가 새 버전으로 업데이트됨
- 확장 프로그램 인스턴스의 구성이 변경됨
이 기능의 가장 중요한 사용 사례 중 하나는 데이터 백필입니다. 예를 들어 Cloud Storage 버킷에 업로드된 이미지의 썸네일 미리보기를 생성하는 확장 프로그램을 빌드한다고 가정하겠습니다. 확장 프로그램의 기본 작업은 onFinalize
Cloud Storage 이벤트에 의해 트리거되는 함수에서 수행됩니다.
그러나 확장 프로그램이 설치된 후에 업로드된 이미지만 처리됩니다. 확장 프로그램에 onInstall
수명 주기 이벤트에 의해 트리거되는 함수를 포함하면 확장 프로그램이 설치될 때 기존 이미지의 썸네일 미리보기를 생성할 수도 있습니다.
수명 주기 이벤트 트리거의 다른 사용 사례에는 다음이 포함됩니다.
- 설치 후 설정 자동화(데이터베이스 레코드 생성, 색인 생성 등)
- 이전 버전과 호환되지 않는 변경사항을 게시해야 하는 경우 업데이트 시 자동으로 데이터 마이그레이션
단기 실행 수명 주기 이벤트 핸들러
태스크를 최대 Cloud Functions 기간(1세대 API 사용 시 9분) 내에 완전히 실행할 수 있는 경우 수명 주기 이벤트 핸들러를 태스크 큐 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
파일에서 다음을 수행합니다.
함수를
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: {}
함수를 하나 이상의 수명 주기 이벤트에 대한 핸들러로 등록합니다.
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
이벤트에 대한 함수를 등록할 수 있습니다. 이러한 이벤트는 모두 선택사항입니다.권장: 확장 프로그램이 작동하는 데 처리 태스크가 필요하지 않은 경우 사용자가 사용 설정 여부를 선택할 수 있도록 사용자 구성 매개변수를 추가합니다.
예를 들어 다음과 같은 매개변수를 추가합니다.
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 기간 내에 태스크를 완료할 수 없는 경우 태스크를 하위 태스크로 분할한 후 Admin SDK의 TaskQueue.enqueue()
메서드를 사용해 작업을 큐에 추가하여 각 하위 태스크를 순서대로 수행합니다.
예를 들어 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 콘솔의 확장 프로그램 세부정보 페이지에서 이 상태를 확인할 수 있습니다.
성공적인 완료 및 심각하지 않은 오류
성공적인 완료 및 심각하지 않은 오류(확장 프로그램이 비작동 상태로 전환되지 않는 오류)를 보고하려면 Admin SDK의 setProcessingState()
확장 프로그램 런타임 메서드를 사용합니다.
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}.` ); 확장 프로그램을 사용할 수 없는 상태로 두는 오류를 보고하려면 |
NONE |
태스크 상태를 삭제하는 데 사용합니다. 필요한 경우 이를 사용하여 콘솔에서 상태 메시지를 삭제할 수 있습니다(예: 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
이러한 매개변수에 대한 자세한 내용은 Google Cloud 문서의 Cloud Tasks 큐 구성을 참조하세요.
태스크 큐 매개변수를 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(
// ...
);
extension.yaml
의 taskQueueTrigger
속성은 확장 프로그램의 태스크 큐를 구성하는 유일한 방법입니다.
예
공식 storage-resize-images
, firestore-bigquery-export
, firestore-translate-text
확장 프로그램은 모두 수명 주기 이벤트 핸들러를 사용하여 데이터를 백필합니다.