111 lines
4.0 KiB
Markdown
111 lines
4.0 KiB
Markdown
# Задачи после code review (2026-04-19)
|
||
|
||
Приоритет: **критично** → сделать до merge в master.
|
||
|
||
---
|
||
|
||
## КРИТИЧНО
|
||
|
||
### 1. k8s ошибки протекают как 502 — нужны правильные HTTP коды
|
||
|
||
**Файл:** `console/main.go`
|
||
**Проблема:** `apierrors.IsAlreadyExists` и `apierrors.IsInvalid` не перехватываются → клиент получает 502 вместо 409/400.
|
||
|
||
**Что сделать:**
|
||
- В `handleCreateFunction`: перехватить `apierrors.IsAlreadyExists` → HTTP 409
|
||
- В `handleCreateFunction`: перехватить `apierrors.IsInvalid` → HTTP 400
|
||
- Аналогично проверить `handleUpdateFunction`
|
||
|
||
**Пример:**
|
||
```go
|
||
if apierrors.IsAlreadyExists(err) {
|
||
writeJSONError(w, http.StatusConflict, fmt.Sprintf("function %q already exists", req.Name))
|
||
return
|
||
}
|
||
if apierrors.IsInvalid(err) {
|
||
writeJSONError(w, http.StatusBadRequest, fmt.Sprintf("invalid function spec: %v", err))
|
||
return
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Валидация имени функции на уровне API
|
||
|
||
**Файл:** `console/main.go`
|
||
**Проблема:** имя с пробелами/спецсимволами уходит в k8s и возвращается 502.
|
||
|
||
**Что сделать:** добавить regex-валидацию сразу после парсинга запроса в `handleCreateFunction` и `handleUpdateFunction`.
|
||
|
||
**Пример:**
|
||
```go
|
||
var validName = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`)
|
||
|
||
if !validName.MatchString(req.Name) || len(req.Name) > 63 {
|
||
writeJSONError(w, http.StatusBadRequest, "invalid function name: must match ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$ and be <= 63 chars")
|
||
return
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ВАЖНО (не блокирует merge)
|
||
|
||
### 3. Reaper: сканирование orphan packages
|
||
|
||
**Файл:** `console/main.go`
|
||
**Проблема:** если под упал в момент удаления функции, Package может остаться без matching Function.
|
||
|
||
**Что сделать:** в цикле reaper дополнительно итерироваться по packages и удалять те, у которых нет соответствующей function с тем же именем (по конвенции `{fn-name}-pkg`).
|
||
|
||
---
|
||
|
||
### 4. Лимит размера кода
|
||
|
||
**Файл:** `console/main.go`
|
||
**Проблема:** нет ограничения на размер `req.Code` — можно залить мегабайты.
|
||
|
||
**Что сделать:** после парсинга тела запроса добавить:
|
||
```go
|
||
const maxCodeSize = 1 << 20 // 1 MB
|
||
if len(req.Code) > maxCodeSize {
|
||
writeJSONError(w, http.StatusBadRequest, "code exceeds 1MB limit")
|
||
return
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5. Namespace race condition
|
||
|
||
**Файл:** `console/main.go`
|
||
**Проблема:** при одновременных первых запросах одного пользователя `Create(namespace)` может вернуть `AlreadyExists`.
|
||
|
||
**Что сделать:** убедиться что в `ensureNamespace` (или аналогичной функции) ошибка `AlreadyExists` при создании namespace игнорируется:
|
||
```go
|
||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||
return err
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## НЕ СРОЧНО
|
||
|
||
### 6. Тест-скрипт: RUN_ID уникальность
|
||
|
||
**Файл:** `tests_v2.sh`
|
||
**Проблема:** два параллельных запуска с одинаковым timestamp дают одинаковый RUN_ID → Block D FAIL.
|
||
|
||
**Что сделать:** добавить случайный суффикс:
|
||
```bash
|
||
RUN_ID=$(date +%s%N | sha256sum | head -c 8)
|
||
```
|
||
|
||
---
|
||
|
||
## Документировать (без кода)
|
||
|
||
- Python env: `def main():` без аргументов — задокументировать в README/examples
|
||
- Версионирование функций — не делать сейчас, отложить
|