meta(handoff): createPickingListPdf деплой 0.11.1 + смоук ✅ оба тенанта — wiki уроки (proxy-server ломает internal render, bookva-api:3000)
This commit is contained in:
@@ -1,45 +1,31 @@
|
|||||||
_Updated: 2026-08-23 — сессия закрыта: деплой a448cad + sched auth/образ + чистка диска vds-kzntsv._
|
_Updated: 2026-08-24 (утро) — сессия: createPickingListPdf задеплоен + смоук ✅ оба тенанта._
|
||||||
|
|
||||||
# NEXT_SESSION
|
# NEXT_SESSION
|
||||||
|
|
||||||
## Последняя сессия (2026-08-23, .admin, вечер)
|
## Последняя сессия (2026-08-24, .admin, утро)
|
||||||
|
|
||||||
**Деплой books-web `master-a448cad` ЗАВЕРШЁН** (фикс удаления picking-list, оба тенанта). Контекст: agenda-remove `master-7ffb560` удалил 8 live embed-api роутов → `DELETE /api/fbs/pickingLists/:id` 404'ил. a448cad вернул их.
|
**createPickingListPdf ЗАРАБОТАЛ на обоих тенантах** (хендофф books 00:45Z, in_reply_to мой смоук-отчёт 22:00Z 23.08).
|
||||||
|
|
||||||
Проделано: локальная сборка по ранбуку (`git archive` → `docker build --secret verdaccio_token` → docker save даёт OCI-структуру сам, `index.json`+`blobs/` → curl-заливка 21 блоба 676МБ → amd64-манифест в `master-a448cad`+`master`, digest `6877d24f…`); Portainer PUT стеков 24 (books-web/slovo, bookva.kzntsv.site) и 46 (bookva-web, bookseller.kzntsv.site) — image + DEPLOY_AT bump, env не тронуты; оба контейнера Up на a448cad.
|
Проделано:
|
||||||
|
- **Пересобрал books-sched-daemon на 0.11.1**: `books/deploy/sched/Dockerfile` FROM 0.11.0→0.11.1, локальная сборка (`docker build --secret verdaccio_token` с пустым контекстом), пуш schema2-флоу (docker save → OCI → amd64 child → трансформ mediaTypes → curl блобы + PUT манифеста; скрипт-образец `/c/tmp/pushimg/push.py`) → теги `master` + `master-0.11.1` (digest `7a43aa96…`).
|
||||||
|
- **Передеплой обоих sched-стеков** (Portainer books: stack 50 books-sched, 51 bookva-sched; portainer.kzntsv.site, X-API-Key из `pass books-vds/full-env` BOOKS_PORTAINER_API_KEY): DEPLOY_AT bump + pullImage:true. Верификация: `@sched/daemon` = 0.11.1 в контейнерах, `/api/tasks` → `config.network: "proxy"`.
|
||||||
|
- **tasks.json обоих тенантов** (jq/node-правки на VDS 89.253.255.133, ssh id_ed25519_books_ops): `network: "proxy"`, `ws://chrome:3000?token=0ffbbc13-…` (direct, БЕЗ stealth/proxy-chain!), реальный API_TOKEN (slovo `81e123d0-8edd-…` из Portainer env books-web).
|
||||||
|
- **Смоук** (ручной триггер `/api/tasks/createPickingListPdf/run`, docker exec node fetch в демоне, Bearer SCHED_ADMIN_KEY из env стека): slovo 429 ✅ (6.8MB → s3://books/fbs-picking-lists/429.pdf), bookva 219 ✅ (1.3MB). `pdf_remote_path` в БД обоих (`fbs_picking_lists.pdf_remote_path`).
|
||||||
|
- **Отчёт books**: `.agents/inbox/2026-08-24T05-44-00Z-.admin.md`.
|
||||||
|
|
||||||
Смоук оба тенанта: DELETE pickingList → `{taskId}` (slovo #428 — юзеровский, bookva #220), `GET /api/fbs/tasks/<uuid>` → success, run в sched daemon (docker exec node fetch localhost:3031/api/runs) → succeeded, лист пропал из списка. Отчёт books: `.agents/inbox/2026-08-23T21-03-33Z-admin.md` (in_reply_to 23-40Z).
|
## 2 находки (записаны в .admin wiki books-vds-no-gitea-actions)
|
||||||
|
|
||||||
|
1. **chrome WS-эндпоинт без `--proxy-server`**: proxy-chain гонит весь трафик (вкл. внутренний books-web:3000) во внешний пул → navigation timeout → browserless job timeout → «Target closed». Direct `ws://chrome:3000?token=…` работает (6.8s/200).
|
||||||
|
2. **bookva-api слушает 3000, НЕ 3021** (slovo books-api — 3021). API_URL bookva исправлен на `http://bookva-api:3000`.
|
||||||
|
|
||||||
## Открыто
|
## Открыто
|
||||||
|
|
||||||
- 🟡 books `createPickingListPdf` (письмо 00:20Z bug-report): auth-фикс сделан (slovo rename docker-config→config.json, bookva ок), образ перезалит в docker-формате (был битый OCI index без child, registry 2.8.3). Смоук вскрыл 2 конфиг-блокера за books-агентом: (1) API_TOKEN плейсхолдер в VDS tasks.json + нет production-конфига daemon в /opt/books/sched; (2) chrome.kzntsv.site → мёртвый 94.19.247.14, browserless/chrome без публичного роута, docker-runner без сети. Отчёт: books inbox 22:00Z. Ждём их фикса → пере-смоук.
|
- 🟡 **books решает по коммитам** (я НЕ пушил, по их просьбе): `books/deploy/sched/Dockerfile` (FROM 0.11.1), `books/deploy/sched-tasks.json`, `bookva-overlay/deploy/sched-tasks.json` (network/endpoint/API_URL) — правки в рабочем дереве, ждут слова юзера/books-агента.
|
||||||
- 🟢 **git push .admin прошёл** (c40f2f41 + handoff 5105f130 на origin/master): локальная сеть ожила сама. Урок: getaddrinfo на этой машине флакает на kzntsv.site (прокси 10808), при этом сайт глобально жив — обход через `--resolve` / hosts.
|
- 🟢 git push .admin wiki (books-vds-no-gitea-actions update) — сделать при случае.
|
||||||
- 🟢 **Чистка диска vds-kzntsv** (алерт провайдера 4.24%): освобождено ~31G (build cache −18.3G, образы −1.9G, verdaccio data-old −6.1G) → свободно 40G (74%). Registry GC НЕ делали: dry-run показал ~2.5МБ реального реклайма (67 eligible, файлы уже удалены прежними GC), риск для OCI-index тегов реален — см. wiki.
|
- graphify `ci.yml` (GitHub Actions) — проверить/решить при случае.
|
||||||
- 🟢 books: **ложная тревога yarn.lock** — `yarn install --immutable` зелёный (их письмо 19:27Z), чистить нечего.
|
|
||||||
- 🟢 **Функциональный смоук ЗАКРЫТ** (письмо books 23:58Z, event: closed): юзер прогнал создание листа подбора, upload-history, карточку товара — все 8 восстановленных роутов работают на обоих тенантах. Инцидент DELETE-404 закрыт полностью. Урок записан books в их wiki (`embed-api-into-web.md` + log): web/server/api = live-API, не удалять «дубли» при рефакторинге api-пакета.
|
|
||||||
- graphify `ci.yml` (GitHub Actions, не Gitea) — проверить/решить при случае.
|
|
||||||
|
|
||||||
## Уроки сессии (предложить wiki-ingest)
|
## Полезное
|
||||||
|
|
||||||
1. Portainer `PUT /api/stacks/{id}` синхронный и тянет образ ВНУТРИ запроса (676МБ через интернет) — клиентский таймаут (90с) рвёт ожидание, но операция доделывается server-side; пере-PUT не нужен, проверяй контейнеры через `/api/endpoints/1/docker/containers/json`. В python urllib ставь timeout 900+.
|
- books-VDS: 89.253.255.133, ssh `id_ed25519_books_ops` (root). Portainer books: `portainer.kzntsv.site` (X-API-Key из pass books-vds/full-env), endpoint 1. Sched-стеки: books-sched=50, bookva-sched=51, chrome=27, proxy-chain=28.
|
||||||
2. `/admin/scheduler/**` (Nuxt proxy → sched daemon) гейтится `requireAdmin` (JWT isAdmin) — `?token=` API-ключ не проходит (403). Для проверки sched: `docker exec <sched-container> node -e 'fetch(...)'` (curl в контейнере нет).
|
- Sched daemon admin API изнутри контейнера: `docker exec books-sched node -e 'fetch("http://127.0.0.1:3031/api/…",{headers:{Authorization:"Bearer <SCHED_ADMIN_KEY>"}})'` (ключ — из env стека). Триггер таски: `POST /api/tasks/:name/run` body `{data, temporary}`.
|
||||||
3. `docker save` на этой машине (Docker 29) сразу даёт OCI-layout (`index.json` + `blobs/sha256/`) — конвертация не нужна; амд64 child manifest — в `index.json` → `blobs/sha256/<index-digest>`.
|
- tasks.json live-reload (~60s поллинг), бэкапы: `/opt/books/sched/tasks.json.bak-20260824`, `/tmp/bookva-tasks.json.bak-20260824`.
|
||||||
|
|
||||||
**Директивы юзера (vitya) — навсегда:**
|
|
||||||
1. **Gitea Actions — НЕ ИСПОЛЬЗОВАТЬ вообще.** Удалены и запушены workflow: books (build/deploy/build-tools/build-sched-daemon) + vds-ops-mcp (там был реальный автобилд `on: push`).
|
|
||||||
2. Раннер на books-vds выпилен полностью: systemd `gitea-runner.service` удалён, `/opt/gitea-runner` стёрт, job-контейнеры `GITEA-ACTIONS-TASK-*` удалены, юзер `gitea-runner` удалён. vds-kzntsv чист. Run 587 заморожен.
|
|
||||||
3. **Сборка образов — только локально на этой машине** (docker build + curl-upload в registry). Деплой — прямыми Portainer PUT (не workflow).
|
|
||||||
|
|
||||||
## Wiki-ingest кандидаты (предложить юзеру)
|
|
||||||
|
|
||||||
1. `.wiki/concepts/books-vds-no-gitea-actions.md` — решение юзера: Actions выпилены, сборка локальная; процедура локальной сборки (docker build + curl-upload блобов, OCI-индекс → amd64 child manifest). [уже в index/log]
|
|
||||||
2. `.wiki/concepts/registry-traefik-buffering-gotcha.md` — большие (>1.5GB) chunked-пуши через traefik (buffering middleware 4GB) умирают «Client Closed Request» на books-vds (RAM 3.9GB, OOM); обход: curl монолитными PUT / POST+PATCH+finalize с drop_caches. [уже в index/log]
|
|
||||||
3. Находка: `custom-environment-variables.json` должен жить в примонтированных конфиг-дирах, иначе `config.get('sched')` THROW — env бесполезен без mapping-файла. [уже в index/log]
|
|
||||||
4. (эта сессия) mappa git-index verify на проде невозможен без чек-аутов — verify = инструмент воркстейшна; прод-импорт из файлов: `DATABASE_URL` внешний + `uselibpqcompat=true&sslmode=require` (pg8 трактует require как verify-full — нужен libpq-compat).
|
|
||||||
5. (эта сессия) sched docker-runner: `docker-config.json` НЕ читается docker CLI (нужен `config.json` в ${DOCKER_CONFIG}); теги из buildx = OCI index, registry:2.8.3 отдаёт их только на OCI-Accept и host-GC рвёт children (→ «manifest unknown»); фикс: пуш docker schema2-манифеста; VDS tasks.json с плейсхолдерами при отсутствии production-конфига daemon в монтированной дире. Кандидат: обновить registry-kzntsv-auth-model / books-vds-no-gitea-actions.
|
|
||||||
|
|
||||||
## Не делать
|
|
||||||
|
|
||||||
- Не диспатчить никакие Gitea Actions (раннер мёртв, workflow удалены — если где-то остались — выпиливать).
|
|
||||||
- Не собирать образы на VDS/раннере — только локально.
|
|
||||||
- Не трогать traefik buffering middleware на registry (4GB) без явной отмашки.
|
|
||||||
|
|||||||
@@ -46,3 +46,22 @@ GET /api/endpoints/1/docker/images/json # образ уже на VD
|
|||||||
**Вторая засада — mediaType образа.** Теги, запушенные buildx (и моим curl-флоу из OCI-save) = **OCI image-index**. registry 2.8.3 отдаёт их ТОЛЬКО на Accept с `application/vnd.oci.image.index.v1+json`; docker daemon (26.1.4) получает «manifest unknown», если child-манифест отсутствует (а он отсутствует после прежних host-GC — см. [[registry-oci-image-index-gc]]). Диагностика: `curl` манифеста тега с docker-only Accept → 404, с OCI-index → 200; child по digest → 404. **Фикс: перепуш образа как docker schema2-манифест** (mediaType `application/vnd.docker.distribution.manifest.v2+json`, config `application/vnd.docker.container.image.v1+json`, layers `application/vnd.docker.image.rootfs.diff.tar.gzip`) — блобы те же (content-addressed), только обёртка; pull снова работает. Сборка: `docker save` → OCI → взять amd64 child → трансформ mediaTypes → PUT в тег с docker Content-Type. Важно: docker config-манифест пишется `container.image.v1+json`, НЕ `distribution.image.config.v2+json` (последний docker не знает → «(unknown)» при pull).
|
**Вторая засада — mediaType образа.** Теги, запушенные buildx (и моим curl-флоу из OCI-save) = **OCI image-index**. registry 2.8.3 отдаёт их ТОЛЬКО на Accept с `application/vnd.oci.image.index.v1+json`; docker daemon (26.1.4) получает «manifest unknown», если child-манифест отсутствует (а он отсутствует после прежних host-GC — см. [[registry-oci-image-index-gc]]). Диагностика: `curl` манифеста тега с docker-only Accept → 404, с OCI-index → 200; child по digest → 404. **Фикс: перепуш образа как docker schema2-манифест** (mediaType `application/vnd.docker.distribution.manifest.v2+json`, config `application/vnd.docker.container.image.v1+json`, layers `application/vnd.docker.image.rootfs.diff.tar.gzip`) — блобы те же (content-addressed), только обёртка; pull снова работает. Сборка: `docker save` → OCI → взять amd64 child → трансформ mediaTypes → PUT в тег с docker Content-Type. Важно: docker config-манифест пишется `container.image.v1+json`, НЕ `distribution.image.config.v2+json` (последний docker не знает → «(unknown)» при pull).
|
||||||
|
|
||||||
**Третий слой — конфиг daemon.** `createPickingListPdf` рендерит print-роут: env берётся из tasks.json на VDS; плейсхолдер `API_TOKEN: "<SET_IN_PROD_VOLUME_MOUNT>"` = production-конфиг daemon'а не задеплоен в монтированную диру (в репо tasks.json — `${config:api.authToken}`). Конфиг-дир `/opt/books/sched/` должен содержать production-overrides (api.authToken, puppeteer.browserWSEndpoint, s3).
|
**Третий слой — конфиг daemon.** `createPickingListPdf` рендерит print-роут: env берётся из tasks.json на VDS; плейсхолдер `API_TOKEN: "<SET_IN_PROD_VOLUME_MOUNT>"` = production-конфиг daemon'а не задеплоен в монтированную диру (в репо tasks.json — `${config:api.authToken}`). Конфиг-дир `/opt/books/sched/` должен содержать production-overrides (api.authToken, puppeteer.browserWSEndpoint, s3).
|
||||||
|
|
||||||
|
## 2026-08-24 — deploy sched-daemon 0.11.1 + createPickingListPdf ЗАРАБОТАЛ (admin)
|
||||||
|
|
||||||
|
Деплой демона на 0.11.1 (docker-runner `config.network`) + фикс tasks.json обоих тенантов → смоук оба тенанта ✅ (slovo 429, bookva 219: PDF в S3 + `pdf_remote_path` в БД).
|
||||||
|
|
||||||
|
**Процедура bump books-sched-daemon (без CI, локальная сборка):**
|
||||||
|
1. `deploy/sched/Dockerfile` FROM → `registry.kzntsv.site/sched-daemon:0.11.1`;
|
||||||
|
2. `VERDACCIO_TOKEN=<jwt> docker build --secret id=verdaccio_token,env=VERDACCIO_TOKEN -f deploy/sched/Dockerfile -t registry.kzntsv.site/books-sched-daemon:master-0.11.1 /c/tmp/schedctx` (пустой контекст — Dockerfile без COPY; НЕ `.` — иначе поедет node_modules);
|
||||||
|
3. пуш schema2-флоу (`docker save` → OCI → amd64 child → трансформ mediaTypes → curl блобы + PUT манифеста) в теги `master` + `master-0.11.1` (скрипт-образец `/c/tmp/pushimg/push.py`);
|
||||||
|
4. Portainer PUT обоих sched-стеков (Id 50 books-sched, Id 51 bookva-sched на portainer.kzntsv.site) — DEPLOY_AT bump + pullImage:true;
|
||||||
|
5. verify: `docker exec books-sched node -e 'require("/app/node_modules/@sched/daemon/package.json").version'` → 0.11.1; admin-api `/api/tasks` → `config.network: "proxy"`.
|
||||||
|
|
||||||
|
**Задачи docker-тасков спавнятся на сети `proxy`** (`config.network: "proxy"` в tasks.json; docker-runner 0.11.1 `docker run --network proxy`) → тул видит `books-web:3000`/`chrome:3000`/`books-api:3021`. tasks.json live-reload — директорный бинд `/opt/books/sched/` (slovo) / volume `bookva-sched-config` (bookva), поллинг ~60с, рестарт не нужен.
|
||||||
|
|
||||||
|
**Готча 1: chrome WS-эндпоинт БЕЗ `--proxy-server`.** Эндпоинт `ws://chrome:3000?token=…&stealth&--proxy-server=http://proxy-chain:8000` ЛОМАЕТ рендер внутренней страницы: proxy-chain гонит весь трафик (включая внутренний `books-web:3000`) во внешний пул → navigation timeout → browserless job timeout → SIGKILL → puppeteer «Protocol error (Page.navigate): Target closed». Внутренний рендер print-роута должен идти напрямую: `ws://chrome:3000?token=0ffbbc13-…` (без stealth, без proxy-флага). `--proxy-server` наследовался от мёртвого внешнего chrome.kzntsv.site.
|
||||||
|
|
||||||
|
**Готча 2: bookva-api слушает 3000, НЕ 3021.** (slovo books-api — 3021, bookva-api — 3000; проверка `docker exec bookva-sched node -e 'fetch("http://bookva-api:3000")'` → 401, на 3021 → ECONNREFUSED). В tasks.json bookva `API_URL` был `http://bookva-api:3021` → PATCH `/fbs/pickingLists/:id/pdf` упал бы. Исправлено на `:3000` (live volume + репо-шаблон).
|
||||||
|
|
||||||
|
**Готча 3: `pdf_remote_path` не виден в `GET /api/fbs/pickingLists/:id`** — api-сериализация листа его не отдаёт; проверять в БД напрямую: `docker exec books-db mysql -ubooks -p… books -e "SELECT id_picking_list, pdf_remote_path FROM fbs_picking_lists WHERE id_picking_list=…"` (таблица `fbs_picking_lists`, колонка `pdf_remote_path`).
|
||||||
|
|||||||
Reference in New Issue
Block a user