Open5
Cloud SchedulerでCloudRun Jobsのバッチ処理を定期実行する構成をTerraformで作る
バッチ処理の概要
connpass apiで現在の日付から1ヶ月分のイベント情報を取得してきてそれをDBに保存する処理
connpass apiの制限
- リクエスト間隔は最低5s
- 一度のリクエストでは最大100件しか取得できない
その他条件
- DBの
events
テーブルに挿入する -
events
テーブルは常に1ヶ月分のデータを保持している- 2回目以降に挿入する場合は現在のデータを全削除する
- 1日1回、午前3:30の定期実行
バッチ処理をGoアプリケーションで作る
Dockerfileの準備
CloudRunにデプロイするためコンテナ化する必要がある。
以下のようなマルチステージビルドで構成する。
# ============ develop ===============
FROM golang:1.21.4-bullseye as dev
WORKDIR /go/src/app
RUN go install github.com/cosmtrek/air@latest
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install git -y
COPY ./go.mod ./go.sum /go/src/app/
RUN go mod download
CMD ["air", "-c", ".air.toml"]
# ============ build ===============
FROM golang:1.21.4-bullseye as build
WORKDIR /go/src/app
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install git -y
COPY go.mod go.sum ./
RUN go mod download
COPY . /go/src/app/
RUN CGO_ENABLED=0 GOOS=linux go build -o /main
# ============ production ===============
FROM gcr.io/distroless/base-debian11 AS production
WORKDIR /go/src/app
EXPOSE 8000
COPY /main /main
ENTRYPOINT ["/main"]
リポジトリは以下
DBの準備
DBはPlanetScaleを使用する。
PlanetScaleでDBを作成して、テーブルを作成するsql文を流し込む
init.sqlファイルを用意
CREATE TABLE `users` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT 'ユーザ名',
`email` varchar(255) NOT NULL COMMENT 'メールアドレス',
`firebase_uid` varchar(255) NOT NULL COMMENT 'Firebaseが持っているID',
`image` varchar(255) NOT NULL COMMENT '表示用写真URL',
`created_at` timestamp,
`updated_at` timestamp
);
CREATE TABLE `events` (
`event_id` INT PRIMARY KEY NOT NULL COMMENT 'イベントID',
`title` VARCHAR(255) NOT NULL COMMENT 'タイトル',
`catch` VARCHAR(255) COMMENT 'キャッチ文章',
`description` TEXT COMMENT '概要',
`event_url` VARCHAR(255) COMMENT 'イベントURL',
`started_at` DATETIME COMMENT '開始日時',
`ended_at` DATETIME COMMENT '終了日時',
`limit` INT COMMENT '定員',
`hash_tag` VARCHAR(100) COMMENT 'ハッシュタグ',
`event_type` VARCHAR(50) COMMENT 'イベントタイプ',
`accepted` INT COMMENT '参加人数',
`waiting` INT COMMENT '補欠人数',
`updated_at` DATETIME COMMENT '更新日時',
`owner_id` INT COMMENT '管理者ID',
`owner_nickname` VARCHAR(255) COMMENT '管理者ニックネーム',
`owner_display_name` VARCHAR(255) COMMENT '管理者名',
`place` VARCHAR(255) COMMENT '開催場所',
`address` VARCHAR(255) COMMENT '開催住所',
`lat` VARCHAR(255) NOT NULL COMMENT '緯度',
`lon` VARCHAR(255) NOT NULL COMMENT '経度'
);
CREATE TABLE `bookmarked_events` (
`event_id` INT PRIMARY KEY NOT NULL COMMENT 'イベントID',
`title` VARCHAR(255) NOT NULL COMMENT 'タイトル',
`catch` VARCHAR(255) COMMENT 'キャッチ文章',
`description` TEXT COMMENT '概要',
`event_url` VARCHAR(255) COMMENT 'イベントURL',
`started_at` DATETIME COMMENT '開始日時',
`ended_at` DATETIME COMMENT '終了日時',
`limit` INT COMMENT '定員',
`hash_tag` VARCHAR(100) COMMENT 'ハッシュタグ',
`event_type` VARCHAR(50) COMMENT 'イベントタイプ',
`accepted` INT COMMENT '参加人数',
`waiting` INT COMMENT '補欠人数',
`updated_at` DATETIME COMMENT '更新日時',
`owner_id` INT COMMENT '管理者ID',
`owner_nickname` VARCHAR(255) COMMENT '管理者ニックネーム',
`owner_display_name` VARCHAR(255) COMMENT '管理者名',
`place` VARCHAR(255) COMMENT '開催場所',
`address` VARCHAR(255) COMMENT '開催住所',
`lat` VARCHAR(255) NOT NULL COMMENT '緯度',
`lon` VARCHAR(255) NOT NULL COMMENT '経度'
);
CREATE TABLE `bookmarks` (
`event_id` INT COMMENT 'イベントID',
`user_id` INT COMMENT 'ユーザID',
PRIMARY KEY (`event_id`, `user_id`)
);
mysql -h <db_host> -u <db_user> -p --ssl-mode=VERIFY_IDENTITY --ssl-ca=/etc/ssl/cert.pem < init.sql
TerraformでGCPリソースの作成
artifact registryの作成
あらかじめAPIを有効化しておく
main.tf
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.51.0"
}
}
}
provider "google" {
credentials = file(var.credentials_file)
project = var.project
region = var.region
}
resource "google_artifact_registry_repository" "devlocator_batch_repository" {
location = var.region
repository_id = var.repository_id_batch
format = "DOCKER"
description = "devlocator batch container repositry"
}
secret managerの作成
あらかじめAPIを有効化しておく
secretmanager.tf
resource "google_secret_manager_secret" "db_password" {
secret_id = "db-password"
lifecycle {
prevent_destroy = true
}
replication {
automatic = true
}
}
resource "google_secret_manager_secret" "db_username" {
secret_id = "db-username"
lifecycle {
prevent_destroy = true
}
replication {
automatic = true
}
}
resource "google_secret_manager_secret" "db_host" {
secret_id = "db-host"
lifecycle {
prevent_destroy = true
}
replication {
automatic = true
}
}
作成したシークレットのバージョンにシークレット値を入れる
CloudRun Jobsの作成
以下のコマンドでCloudRun Jobsを作成する
gcloud run jobs create [JOB_NAME] \
--image=[ARTIFACT_REGISTRY_URL]/[PROJECT_ID]/[REPOSITORY]/[IMAGE]:[TAG] \
--region=[REGION]
すると以下のようにジョブ
タブにジョブが作成される。
環境変数の設定
ジョブの編集でSecret Manager
に設定したシークレットを設定する
手動実行して成功することを確認!