完成当前打印任务

DockerBeginner
立即练习

介绍

Paper & Pine 现在需要在停止前完成一份十二页社区节目单。入口已能正确传递 SIGTERM,但 Compose 的一秒宽限期在真实 PDF 完成前就截断了 worker。你将设置有限、可复用且留有余量的宽限期,同时不启动下一任务。

请先完成 Deliver the Stop Signal,或了解其中的入口 shell、PID 1、TERM/KILL 区别、任务观察及基本 Compose 命令。本独立实验准备了自己的节目单、较早 PDF、练习队列和交付队列。无需之前 VM 的文件、Python 编程或实体打印机。

使用 Workstation 和 Print Desk。第一页暂停及剩余页面每页 0.5 秒的节流是已披露的训练行为。停止宽限期从发出停止请求时开始,而非 worker 首次进入暂停时开始。包含阅读和普通错误在内,预计约 45 分钟;这是作者估计。

给当前节目单足够的完成时间

本步骤将区分信号成功送达与完成时间充足,然后让原交付任务在有限的 Compose 宽限期内完成。

确认工作与当前时间预算

从 Print Desk 开始。在 Delivery attempt 下预览并下载已完成的 Morning welcome handout。当前 Community open day programme 需要十二页真实 PDF;Volunteer notes 是后续任务,必须保持待处理。练习与交付是具有独立文件的独立训练队列。

切换到 Workstation,从 /home/labex/project/print-grace 开始:

cd /home/labex/project/print-grace
cat entry.sh
cat compose.yaml

入口已经使用 exec python3 -B /app/worker.py,因此提供的 worker 会替换 shell 并接收 Docker 的 TERM 请求。问题在于 stop_grace_period: 1s。训练暂停结束后,剩余十一个间隔各需 0.5 秒,加上 PDF 最终生成,需要超过一秒。在请求停止前多等一会儿不会增加宽限期:worker 刻意等待 TERM 后才继续完成当前任务。

保持已准备的镜像、用户 ID、挂载、输入节目单及其他 Compose 设置不变。你只调整有限的停止时间预算;无限等待不是期望结果。

观察真实截断的练习尝试

启动提供的练习项目:

docker compose -f compose.trial.yaml -p print-trial up -d --pull never --no-build

切换到 Print Desk,刷新并等待 Practice attempt 显示第一页训练暂停。切回 Workstation,请求使用其一秒宽限期停止:

docker compose -f compose.trial.yaml -p print-trial stop worker
docker inspect print-trial --format '{{.State.ExitCode}}'
docker logs print-trial

Docker 停止操作可返回 0,而 worker 的退出代码为 137。与上一实验中错误 shell 导致的失败不同,这里的日志包含 stop-received,也可能有一些剩余页面事件,但没有完整的十二页 PDF 和正常完成事件。信号成功送达;宽限期在真实剩余工作期间耗尽。

切换到 Print Desk 并刷新。练习没有最终完成的当前节目单下载。较早 PDF 和未触碰的交付队列保持完好。不要用第二个处理进程补齐缺失成果。

在交付开始前保存有限的 Compose 覆盖配置

切换到 Workstation。简短覆盖文件可以保留原始基础文件,仅更改停止时间预算。两个 -f 参数按顺序合并文件;后一个 services.worker.stop_grace_period 覆盖该属性。检查配置、启动和停止时都使用同一文件对。

选择不超过 30 秒、以整秒计的有限宽限期。十五秒为此已披露的训练节目单留出了剩余页面和普通调度开销所需空间。这是实用余量,不表示所有生产 PDF 都能在此时间内完成。

使用第一个引导实验所教的按字面保存的 here-document 保存 compose.stop.yaml:

cat > compose.stop.yaml <<'COMPOSE'
services:
  worker:
    stop_grace_period: 15s
COMPOSE
docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery config

在生效配置中找到 stop_grace_period: 15s。已准备的镜像、数字用户、入口脚本和只读输入保持不变。如果 YAML 缩进错误,修正这个短文本块,启动前再次解析。修改文件不会改写已创建容器的默认值,因此应在启动交付前保存预算。

使用同一文件对启动交付:

docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery up -d --pull never --no-build

切换到 Print Desk,刷新并等待 Delivery attempt 显示训练暂停。然后切换到 Workstation,使用相同的生效配置停止它:

docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery stop worker
docker inspect print-delivery --format '{{.State.ExitCode}}'
docker logs print-delivery

worker 应在记录 stop-received、全部十二个页面事件、当前任务的 completed 和 worker-stopped 后以 0 退出。从接收请求到完成节目单,其运行和进程身份保持相同。保留此已停止容器;不要为了清理而删除它。

使用完整 PDF 并保留其他工作

切换到 Print Desk,刷新,在 Delivery attempt 下选择当前节目单的 Preview text。它解码实际保存的 PDF。检查第一页、最后一页及中间所有章节标题和页码。下载节目单并打开其十二页。返回服务台,确认上午讲义未变,Volunteer notes 仍为待处理且没有 PDF。

现在交付拥有正常停止的 worker 和真实的十二页下载。练习仍清楚显示失败,后续任务保持待处理:

完整节目单完成后的 Print Desk

检查结合真实 Docker TERM/退出事实、原 worker 身份、实际解码页面内容及队列保留情况。一次性重放会在另一节目单上测试保存的入口和生效的有限宽限期。它不会向实时 worker 发信号或修复它。

恢复失败的交付

如果交付尝试失败,先保留停止的容器,读取日志和退出状态。仅修正入口或宽限期配置。提供的恢复操作会拒绝正在运行或已成功完成的容器;对于失败且已停止的课程 worker,它只将当前任务重新排队,并将失败产物保留在 delivery/attempt-history/。它保留较早 PDF、原始输入及后续待处理任务:

python3 /opt/labex/dk05/source/retry.py

显式恢复后,用 docker compose -p print-delivery down 仅移除失败交付项目的容器,再重复所示交付启动、等待暂停和停止流程。不会重新生成源 PDF,标签页或评分检查也绝不会运行此恢复。不要重置 VM 或更改队列 JSON 来掩盖失败尝试。

总结

你区分了收到停止请求与有足够时间完成当前任务。保存的有限 Compose 宽限期让原 worker 完成全部十二页 PDF,正常退出,并保留较早输出及后续待处理任务。