# Отчёт 2026-04-26 — Layer2 console, live validation и причина NodeJS сбоя ## Цель Зафиксировать текущее состояние Layer2 API и console UI в репозитории fission, задокументировать выполненные live-проверки и отдельно разобрать корневую причину, по которой NodeJS-функции раньше создавались, но не вызывались. ## Что было сделано в этой сессии ### 1. Namespace status/debug приведён к реальному layer1 поведению Старый код статуса namespace не соответствовал watcher-based схеме из layer1. В console backend логика была перепривязана к реальной модели readiness и bootstrap. Сделано: - добавлена актуальная проверка состояния namespace и control-plane; - добавлен debug endpoint для UI; - wiring зарегистрирован в HTTP server. Основные точки: - [console/internal/api/ns_status.go](console/internal/api/ns_status.go) - [console/internal/api/server.go](console/internal/api/server.go) ### 2. UI стал показывать прогресс и причины задержек В UI добавлена более явная обратная связь по долгим операциям: - таймер deploy/invoke; - стадия выполнения; - причина задержки, если функция ещё не готова; - более явное сообщение об ошибке invoke/deploy. Это было нужно для демонстрации: пользователь не должен видеть просто зависание без контекста. Основная точка: - [console/ui/index.html](console/ui/index.html) ### 3. Go выведен из текущего demo-сценария Go не удалялся из backend-логики целиком, но был исключён из текущего UI create-flow и из оперативного demo-фокуса. Причина практическая: это единственный компилируемый язык в текущем наборе, а на стенде он зависал на build pending и не был нужен для ближайшей демонстрации. Основная точка: - [console/ui/index.html](console/ui/index.html) ### 4. NodeJS починен на уровне packaging + entrypoint compatibility Это был главный runtime-дефект в конце сессии. Изменения: - backend-упаковщик NodeJS теперь экспортирует сразу `main`, `handler` и `default`; - UI-шаблон NodeJS создаёт новые функции с entrypoint `main`; - добавлен узкий unit-test на содержимое zip wrapper. Основные точки: - [console/internal/runtime/nodejs.go](console/internal/runtime/nodejs.go) - [console/internal/runtime/nodejs_test.go](console/internal/runtime/nodejs_test.go) - [console/internal/runtime/entrypoint.go](console/internal/runtime/entrypoint.go) - [console/ui/index.html](console/ui/index.html) ## Почему NodeJS не работал ### Симптом Свежесозданная NodeJS-функция успешно создавалась, package имел `buildstatus: none`, poolmgr pod поднимался, но invoke стабильно возвращал timeout: `invoke "node-..." timeout after 20s: function specialization likely failed` ### Что показала диагностика В кластере у сломанной функции одновременно наблюдалось следующее: 1. В backend default entrypoint для NodeJS уже был `main`. См. [console/internal/runtime/entrypoint.go](console/internal/runtime/entrypoint.go). 2. В UI исторический шаблон NodeJS создавал функцию с entrypoint `handler`. 3. Генерируемый `main.js` wrapper не экспортировал именованные entrypoint-ы `main` и `handler` одновременно. По факту он не обеспечивал совместимость между старым UI-поведением и backend default semantics. 4. В результате в `Function.spec.package.functionName` оказывался `handler`, а в содержимом package literal не было гарантированной совместимой named export для этого имени. 5. Fission specialization доходил до стадии загрузки кода, но не мог корректно разрешить entrypoint и заканчивал таймаутом specialization. ### Корневая причина Корневая причина была не в builder, не в Package CRD и не в самом создании environment. Проблема была в несовместимости между: - ожидаемым именем entrypoint в Function spec; - историческим значением entrypoint из UI; - фактически экспортируемыми символами в NodeJS wrapper. Коротко: backend и UI расходились по имени entrypoint, а zip wrapper не был сделан обратносуместимым. ### Исправление В [console/internal/runtime/nodejs.go](console/internal/runtime/nodejs.go) wrapper был изменён так, чтобы: - разрешать user code как function, default, handler или main; - экспортировать `__invoke` сразу как `main` и как `handler`; - сохранить также `default` export. Ключевой фрагмент поведения теперь такой: - поиск callable идёт через `_fn.default || _fn.handler || _fn.main`; - наружу wrapper экспортирует `main`, `handler`, `default`. Это снимает несовместимость и для старых client-side ожиданий, и для нового backend default entrypoint. ### Проверка исправления 1. Unit validation: - `go test ./internal/runtime ./internal/api ./cmd/server` — PASS. 2. Live rollout: - выкачен image `naeel/fission-console:v0.8.17`; - deployment `fission-console` успешно обновлён до этого образа. 3. Live retest после rollout: - создана свежая NodeJS-функция через public console API; - create вернул `201`; - первый же invoke вернул `200` и `node-fix-ok`. Вывод: проблема была именно в entrypoint/export compatibility, и на новых функциях после rollout она устранена. Важно: уже созданные до фикса NodeJS-функции не чинятся автоматически, потому что их старый package literal уже записан в кластере. ## Что проверено живыми тестами ### Языки К моменту завершения фикса подтверждено: - Python: deploy/invoke PASS; - PHP: deploy/invoke PASS; - Ruby: deploy/invoke PASS; - NodeJS: после выката `v0.8.17` deploy/invoke PASS на свежей функции; - Go: исключён из текущего demo-path. - Perl: исключён из текущего demo-path после нестабильного specialization в `perl-env`. ### Многопользовательский сценарий Прогон с 10 параллельными пользователями показал: - `CREATE_OK=10/10`; - `INVOKE_OK=10/10`. Отдельно ранее наблюдался шум на первичном init (`GET /functions`) с частью ответов `000000`, то есть проблема была не в create/invoke-конвейере, а в кратковременной нестабильности первичного запроса или timeout-режима самого тестового скрипта. ## Что важно помнить перед следующим циклом тестов 1. Для длинных прогонов на этом стенде безопаснее использовать self-completing SSH-команды с жёсткими timeout, а не фоновые или интерактивные сценарии. 2. Для NodeJS нужно тестировать только новые функции, созданные уже после rollout исправленного console image. 3. Для demo сейчас приоритетны Python, NodeJS, PHP, Ruby. 4. Go в UI скрыт намеренно и не должен снова появиться в create-flow до отдельного решения по builder path. ## Автоочистка test namespace После серии прогонов на стенде начали накапливаться десятки и сотни user namespace от тестов. Это мешает ручной диагностике и засоряет cluster state. Чтобы это больше не копилось: - добавлен helper [cleanup_test_namespaces.sh](cleanup_test_namespaces.sh); - [tests_v2.sh](tests_v2.sh) теперь в `trap EXIT` удаляет все namespace, созданные своими test sub; - [test_multitenant_ns.sh](test_multitenant_ns.sh) тоже удаляет свои namespace по завершении, включая аварийный выход. Дополнительно на стенде был запущен разовый cleanup накопившихся test namespace с префиксами `fission-`, `diag-`, `l1-test-`, `rbac-verify-`, `sa-verify-`. ## Следующий шаг Следующий практический шаг после этого отчёта: - удалить все текущие Fission-функции и managed namespaces; - затем прогнать новый набор тестов с нуля; - отдельно включить сценарии, которые имитируют пользовательские ошибки в UI: пустые поля, дубли, неверный entrypoint, плохой код, ранний invoke и повторные клики. ## Обновление: удаление Perl из demo-path После отдельной проверки выяснилось, что Perl ломается не только в multi-tenant console path, но и на обычном single-user Fission через `simple-perl-env` в `default` namespace. Поэтому для demo-path Perl был отключён на стороне console. Что изменено: - Perl убран из UI create-flow; - Perl убран из supported language map console-side; - Perl убран из `ai/check` language set; - Perl убран из live regression сценариев demo-path. Live rollout: - собран и выкачен image `naeel/fission-console:v0.8.19`; - deployment `fission-console` обновлён до `naeel/fission-console:v0.8.19`; - rollout completed successfully. Что проверено после rollout `v0.8.19`: - `go test ./internal/... ./cmd/server/...` — PASS; - `bash ./test_linters.sh` — PASS (`PASS=31 FAIL=0`); - `KUBECTL_DIRECT=1 ./test_ui_user_flows.sh` — PASS (`PASS=26 FAIL=0`), после усиления invoke-диагностики и разведения Python / Node / PHP+Ruby по разным user namespaces; - `KUBECTL_DIRECT=1 ./smoke_live_multiuser.sh 10` — `CREATE_OK=10/10`, `INVOKE_OK=10/10`, но первичный init дал `INIT_OK=6/10` из-за кратковременных `GET /functions -> 000000`; - после добавления retry в init: `KUBECTL_DIRECT=1 ./smoke_live_multiuser.sh 10` — `INIT_OK=10/10`, `CREATE_OK=10/10`, `INVOKE_OK=10/10`; - новый параллельный сценарий `KUBECTL_DIRECT=1 ./smoke_user_journeys.sh 5` — `USER_JOURNEYS_PASS=5/5`; - Python / NodeJS / PHP / Ruby demo-path остаются рабочими; - Perl отсутствует в live UI surface намеренно. Отдельно зафиксирована причина ложного падения прежнего `test_ui_user_flows.sh`: это был не баг PHP/Ruby runtime и не ошибка create-path, а quota одного user namespace. Когда в одном и том же namespace последовательно держались Python, NodeJS update и затем PHP/Ruby poolmgr pod'ы, Fission ловил `exceeded quota: user-quota, requested: limits.cpu=1, used: limits.cpu=4, limited: limits.cpu=4`, после чего invoke возвращал `timeout after 20s: function specialization likely failed`. Для live user-flow smoke сценарии были разведены по разным test users/namespaces, сохранив совместную проверку PHP+Ruby в одном namespace. Дополнительно исправлены сами тесты: - `test_multitenant_ns.sh` больше не использует устаревший SSH key path; - `test_multitenant_ns.sh` теперь JSON-экранирует многострочный Python code payload при create function.