部署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個檔案:

  1. cron-job.guard.ts - 寫檢核邏輯
  2. 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' }),
    );
  }

其他注意事項

  1. 部署時,單純指令gcloud app deploy cron.yaml就可以馬上部署,且速度很快
  2. GCP網頁有按鈕可以直接觸發批次作業即刻驗證執行狀況
  3. 部署成功後,可以再Cron工作頁面看到
  4. 在GCP頁面點擊Cron工作時,會引導到CLOUD SCHEDULER,一點進去時會是空的,不是沒部署成功。點擊上方APP ENGINE CRON工作。就會看到cron.yaml裡寫好的批次作業了
  5. 可以點擊立即執行確認批次作業是否正常

參考資料

stack overflow / Every day,week,month,year in AppEngine cron (python)

系列文章

部署Nest.Js至GAE系列文章