部署Nest.Js至GAE(五):使用Cron.yaml執行批次作業
前言
在Nest.Js裡,通常會使用nestjs/Schedule
執行批次作業
但GAE裡,會動態依其使用情況暫停服務
所以設定好的批次作業是不會執行的
除非剛好當時服務正在啟動狀態
為此,GCP有額外提供cron.yaml
觸發批次作業
這個就相對簡單許多,基本上照著官方教學就可以順利完成
只要把原本寫批次作業的service
在其controller
增加@Get()
路由
當執行成功後回傳200~299
,則GCP會當作執行成功
由於已不需要nestjs/Schedule
,記得將此模組刪除
指定批次執行時間
還是得抱怨一下GCP官方文件
雖然cron.yaml
用法、格式都寫的滿清晰的
但最單純、最常用的指定時間執行批次,竟然沒有範例!
用Node.Js當關鍵字去搜時,還找不到範例= =
最後在Python的詢問資訊裡找到…
# Daily:
every day 00:00
# Weekly:
every monday 00:00
# Monthly:
1 of month 00:00
# Yearly:
1 of jan 00:00
至於一些其他較特別的時間區段
官方文件就有範例,參考官方範例應該就寫的出來了
批次作業權限保護
由於有對外路由,就需要增加權限保護了
官方文件有說明檢查HEADER有無X-Appengine-Cron: true
就可以了
若有人從外部手動增加此HEADER打批次作業API,GAE會自動清除掉,應不必擔心
增加2個檔案:
cron-job.guard.ts
- 寫檢核邏輯cron-guard.ts
- 供controller
裝飾
cron-job.guard.ts
只需要很單純的檢查header的X-Appengine-Cron
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Request } from 'express';
@Injectable()
export class CronJobGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const req = context.switchToHttp().getRequest<Request>();
return req.get('X-Appengine-Cron') === 'true';
}
}
cron-guard.ts
使用自定裝飾器,封裝寫法
因我有使用全域guard保護所有路由(須登入才可以使用)
也照著Nest.Js官方教學增加@Public()
裝飾器對於不須權限的路由做例外處理
而cron job也算例外的一部份,但又需額外做保護
故我增加一自定義裝飾器@CronGuard()
寫法如下
import { applyDecorators, UseGuards } from "@nestjs/common";
import { ApiBearerAuth, ApiUnauthorizedResponse } from "@nestjs/swagger";
import { Public } from "../../core/decorators";
import { CronJobGuard } from "./cron-job.guard";
export function CronGuard() {
return applyDecorators(
Public(),
UseGuards(CronJobGuard),
ApiBearerAuth(),
ApiUnauthorizedResponse({ description: 'Unauthorized' }),
);
}
其他注意事項
- 部署時,單純指令
gcloud app deploy cron.yaml
就可以馬上部署,且速度很快 - GCP網頁有按鈕可以直接觸發批次作業即刻驗證執行狀況
- 部署成功後,可以再
Cron工作
頁面看到 - 在GCP頁面點擊
Cron工作
時,會引導到CLOUD SCHEDULER
,一點進去時會是空的,不是沒部署成功。點擊上方APP ENGINE CRON工作
。就會看到cron.yaml
裡寫好的批次作業了 - 可以點擊
立即執行
確認批次作業是否正常
參考資料
stack overflow / Every day,week,month,year in AppEngine cron (python)