# syntax=docker/dockerfile:1
#
# Temporal Worker 镜像
#
# Build context: temporal/worker/
#   docker build -t gadmin-workflow-worker -f temporal/worker/Dockerfile temporal/worker
#
# Worker 通过 require.resolve('./workflows/dsl-workflow') 在运行时加载已编译的
# workflow JS，无需 bundleWorkflowCode 预打包。
#
# 为什么用 node:20-slim 不用 node:20-alpine：
#   @temporalio/core-bridge 的 native binding 是 glibc 二进制。alpine 用 musl libc，
#   会在 require 时报 "Error relocating ...: __register_atfork: symbol not found" 直接崩。
#   slim 是 debian-bookworm-slim 基底，glibc，体积也只比 alpine 大几十 MB。

# ─── 阶段 1：构建 ────────────────────────────────────────────
FROM node:20-slim AS builder

WORKDIR /app

# 禁止 husky 在无 .git 环境下报错
ENV HUSKY=0

# 先复制依赖描述文件，源码未变时此层可复用缓存
COPY package.json yarn.lock ./

# 安装全量依赖（含 devDependencies，用于 TypeScript 编译）
RUN --mount=type=cache,target=/root/.yarn \
    yarn install --frozen-lockfile

# 复制源码与 tsconfig
COPY tsconfig.json ./
COPY src/ ./src/

# 编译 TypeScript → dist/
RUN yarn build

# ─── 阶段 2：运行 ────────────────────────────────────────────
FROM node:20-slim AS runner

# 时区：与 server 保持一致。debian-slim 不预装 tzdata，需要 apt 装一下。
RUN apt-get update && \
    apt-get install -y --no-install-recommends tzdata && \
    rm -rf /var/lib/apt/lists/* && \
    ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone
ENV TZ=Asia/Shanghai

WORKDIR /app

# 优雅关闭：让 Node 进程（PID 1）直接收到 SIGTERM 后调用 worker.shutdown()
STOPSIGNAL SIGTERM

ENV HUSKY=0 \
    NODE_ENV=production

# 先复制依赖描述文件
COPY --chown=node:node package.json yarn.lock ./

# 只安装 production 依赖，大幅减少镜像体积
RUN --mount=type=cache,target=/root/.yarn \
    yarn install --production --frozen-lockfile

# 从构建阶段复制编译产物（不带源码）
COPY --from=builder --chown=node:node /app/dist ./dist

# 切换到非 root 用户（node 镜像内置 uid/gid 1000）
USER node

# Worker 仅出站连接 Temporal Server (7233) 与 PostgreSQL；额外暴露 :8081 供 K8s probe 访问 health 端点
EXPOSE 8081

# 容器健康检查：调用 worker 内置的 /health/live 端点。
# debian-slim 不带 wget/curl，用 node 自带 http 模块代替（零额外依赖、~10ms 开销）。
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
    CMD node -e "require('http').get('http://127.0.0.1:8081/health/live',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))" || exit 1

# exec form 确保 node 作为 PID 1 直接接收 SIGTERM
CMD ["node", "dist/index.js"]
