Tổng › Không gấp
2. Không gấp — dev tự sắp lịch
A. Tải, hàng chờ, provider
K1APIKiểm slot KIE không nguyên tử
- Vấn đề
- Trần 90 job tổng và 20 job/user được kiểm bằng
COUNTrồi mớiUPDATE. Khi nhiều worker cùng kiểm lúc còn 1 slot, cả nhóm cùng thấy còn chỗ và cùng vượt trần. - Vị trí
- apps/api/src/jobs/job-lifecycle.service.ts:757–759
- Thực hiện
- Đặt chỗ nguyên tử: advisory lock, hoặc hàng đếm khóa bằng
FOR UPDATE. - Kiểm
- Test đồng thời ở biên 89→90: không vượt 90.
K2APILimiter submit theo queue, không theo tài khoản KIE
- Vấn đề
-
- Mặc định 16 request/10 s cho mỗi queue. Main và test là hai queue riêng.
- KIE công bố 20 request tạo task/10 s cho mỗi tài khoản.
- Nếu hai queue dùng chung key, tổng có thể lên 32/10 s, vượt mức của tài khoản.
- Vị trí
- apps/api/src/config/env.ts:62–63, apps/api/src/jobs/job-queue.service.ts:48–49 · docs.kie.ai
- Thực hiện
- Dùng limiter chung theo tài khoản provider, hoặc cấp key riêng cho queue test.
- Kiểm
- Bắn burst ở cả hai queue với provider giả lập: tổng số submit trong mỗi cửa sổ 10 s không vượt 20.
K3APIPreview output đi qua một encoder duy nhất cho toàn hệ thống
- Vấn đề
-
- Một lease DB khiến các process encode preview lần lượt từng cái.
- Hàng chờ tối đa 40 ảnh / 128 MiB.
- Khi nhiều job xong cùng lúc, provider đã trả kết quả nhưng UI chưa thấy output. Thêm replica API cũng không tăng được throughput chỗ này.
- Vị trí
- apps/api/src/storage/output-preview.service.ts:20–21, :59–67
- Thực hiện
- Đo thời gian từ provider_done đến succeeded trước. Sau đó cân nhắc cho phép nhiều encoder theo RAM đã đo, hoặc đánh dấu job xong trước rồi tạo preview sau.
- Kiểm
- p95 từ provider_done đến succeeded với 20 job hoàn tất cùng lúc (output giả lập).
K4APIUpload chỉ nhận 2 request mỗi process, trong đó 1 source
- Vấn đề
- Vượt giới hạn trả
503 upload_busy. FE thử lại sau 5 s và 8 s, tổng 3 lần. Khi vài user upload cùng lúc sẽ có lượt thất bại. Đây là giới hạn có chủ đích để giữ RAM (API giới hạn 1 GiB). - Vị trí
- apps/api/src/storage/upload-admission.ts:12, apps/web/src/lib/customer/upload.ts:6
- Thực hiện
- Đo RSS khi decode ảnh 8 / 32 / 64 MP rồi mới đặt giới hạn theo RAM. Không nâng giới hạn khi chưa đo.
- Kiểm
- Upload đồng thời 1/2/4/8 file: không OOM, lỗi trả đúng mã, retry không tạo asset trùng.
K5APIMultiple Angles / Topaz (FAL): hạn URL nguồn, deadline và retry không khớp nhau
- Vấn đề
-
- URL ảnh nguồn được ký 600 s, job có deadline 15 phút, và không gửi
X-Fal-Request-Start-Timeout. - Nếu queue FAL chờ lâu: URL hết hạn trước khi model tải ảnh, hoặc API báo job hết hạn trong khi FAL vẫn còn giữ request.
- Header
X-Fal-No-Retry: 1đang tắt cơ chế retry của FAL. Cần quyết định có giữ không.
- URL ảnh nguồn được ký 600 s, job có deadline 15 phút, và không gửi
- Vị trí
- apps/api/src/config/env.ts:76, apps/api/src/jobs/job-timing.ts:2, job-lifecycle.service.ts:806, fal-orbit.client.ts:35 · FAL Queue, FAL reliability
- Thực hiện
- Đặt start-timeout của FAL ngắn hơn hạn URL. Khi hết deadline, đọc trạng thái FAL trước rồi mới fail, hoặc gửi lệnh hủy.
- Kiểm
- Provider giả lập giữ
IN_QUEUEquá 10 phút: job kết thúc rõ ràng, không bị tính phí hai lần.
B. Core và contract
K6API + CoreCore trả 413 (body quá 256 000 B) nhưng API báo lỗi chung
- Vấn đề
-
- API nhận JSON tới 1 MiB, còn Core giới hạn 256 000 B.
http-core-clientchỉ phân biệt400 INVALID_INPUT; mọi mã khác trảnull, thànhgeneration_mode_unavailable.
- Vị trí
- services/core-engine/src/server.mjs:49, apps/api/src/core/http-core-client.ts:68–70, function-params.ts:85, :118
- Thực hiện
- Map 413 sang một mã lỗi riêng, và kiểm số byte ở API trước khi gọi compile.
- Kiểm
- Test body dưới / đúng / trên trần: trả lỗi đúng mã, provider dispatch = 0.
K7APIPhiên bản policy lệch: API v8, Core v17
- Vấn đề
- API công bố
commercial_room_edit_v8trong khi Core đang chạyv17. Metadata và receipt ghi sai phiên bản, gây khó chẩn đoán. Không làm Run lỗi. - Vị trí
- apps/api/src/core/commercial-presets.ts:9, services/core-engine/src/commercial-policy.mjs:13
- Thực hiện
- Lấy một nguồn phiên bản duy nhất. Thêm test để phát hiện khi hai bên lệch nhau.
- Kiểm
- Test so sánh hai hằng số.
K8API + CoreLayer extract gửi 2K + transparent
- Vấn đề
-
Sau khi sửa một layer, worker lấy lại vật thể bằng Sunburst ở 2K với nền trong suốt, và Core bắt buộc đúng tổ hợp này.
Schema KIE ghi
backgroundchỉ áp dụng ở 1K, nên extract có thể trả về ảnh không có alpha. Bước Recraft remove-background chạy ngay sau đó, nên kết quả cuối có thể vẫn đúng. Chưa kiểm bằng lần chạy thật. - Vị trí
- apps/api/src/jobs/layer-output.service.ts:443–447, services/core-engine/src/engine.mjs:329–332
- Thực hiện
- Chạy thật 1 lần, xem extract có alpha không, rồi mới quyết định sửa. Không tự hạ xuống 1K, không bỏ bước alpha.
- Kiểm
- Ảnh extract và ảnh alpha cuối có kênh trong suốt, viền vật thể đúng.
K9CoreInstruction gate LLM gửi content dạng chuỗi (chỉ khi bật)
- Vấn đề
- Schema KIE
gpt-5-2mô tảmessages[].contentlà mảng, còn code gửi chuỗi. Gate mặc định tắt (INSTRUCTION_GATE_LLM=off). - Vị trí
- services/core-engine/src/instruction-gate/kie-llm.mjs:28–45
- Thực hiện
- Chỉ sửa khi có kế hoạch bật gate.
- Kiểm
- Test payload đúng schema trước khi bật env.
C. Dữ liệu, lưu trữ, vận hành
K10API + FEKhông có API lấy một workspace theo ID
- Vấn đề
- Để mở một project, FE duyệt danh sách phân trang tới khi gặp. Project nằm ở trang sau phải đợi thêm các request tuần tự và tải metadata không cần thiết.
- Vị trí
- apps/web/src/lib/customer/find-workspace.ts:4–12,
apps/api/src/jobs/projects.controller.ts - Thực hiện
- Thêm
GET /projects/workspaces/:idcó kiểm quyền sở hữu, và FE chuyển sang dùng endpoint này. - Kiểm
- Số request khi mở project ở trang thứ 3 giảm còn 1.
K11API + FEPolling job nhân theo số tab
- Vấn đề
- Mỗi tab đang hiện trên màn hình gọi list 100 job mỗi 3 s. Job không có trong list thì đọc riêng từng job, 4 request song song. Mở 100 tab là khoảng 33 request list mỗi giây, chưa tính các request đọc lẻ.
- Vị trí
- apps/web/src/hooks/useGeneration.ts:38, :232
- Thực hiện
- Thêm endpoint đọc nhiều job theo danh sách ID. Chỉ poll những job đang chạy; giữ nguyên cơ chế dừng poll khi tab ẩn.
- Kiểm
- Đo số request/phút với 1, 10 và 128 job, ở 1 tab và 3 tab.
K12APIẢnh private trả no-store
- Vấn đề
- Mỗi lần xem lại ảnh đều phải đi qua API và R2, tốn băng thông và tăng độ trễ khi mở Studio hoặc Library.
- Vị trí
- apps/api/src/storage/media.controller.ts:18
- Thực hiện
- Với asset bất biến đã kiểm quyền:
private, max-age+immutable. Output đang khóa và file download giữno-store. - Kiểm
- Mở lại Studio lần 2: ảnh lấy từ cache. Đổi sang tài khoản khác thì không xem được ảnh.
K13InfraRedis, DB pool, journal Core, ổ đĩa
- Vấn đề
-
- Redis chạy
noevictionvới 512 MB. Hết bộ nhớ thì từ chối ghi, nên auth, rate-limit và queue cùng dừng. - DB pool mặc định 10, chờ lấy kết nối tối đa 5 s.
- Journal SQLite của Core chưa có retention.
- DB/WAL, Redis AOF, journal, log và Docker cùng nằm trên đĩa local 160 GB.
- Redis chạy
- Vị trí
- docker-compose.prod.yml:68–70, apps/api/src/db/db.service.ts:25–29, services/core-engine/src/store.mjs:9
- Thực hiện
-
- Đặt cảnh báo: bộ nhớ Redis > 70 %, thời gian chờ pool p95 > 100 ms, đĩa > 70 %.
- Thêm retention cho journal, nhưng vẫn giữ đủ bản ghi để chống dispatch trùng.
- Kiểm
- Restart Redis/Core: job đã nhận không mất. Theo dõi tốc độ tăng dung lượng mỗi ngày.
K14APIR2 không có quota dung lượng và không dọn blob
- Vấn đề
- Các đường upload và lưu output không kiểm tổng dung lượng theo tài khoản, cũng không có lifecycle cho guest, blob mồ côi hay phiên bản phụ. 300 upload/giờ là giới hạn tần suất, không phải quota dung lượng.
- Vị trí
apps/api/src/storage/assets.service.ts(createInput / createSource / recordOutput)- Thực hiện
- Đo dung lượng thật trên mỗi ảnh trước, rồi đặt quota hoặc retention theo gói.
- Kiểm
- Báo cáo số byte đang dùng theo account; danh sách blob mồ côi theo tuổi.
D. Frontend
K15FE + APIMở Studio qua chuỗi request nối tiếp
- Vấn đề
-
- Thứ tự hiện tại: refresh phiên → list/profile →
createWorkspace→ điều hướng. Mỗi bước phải chờ bước trước. - Màn trống vẫn tải sẵn
EditorWorkspace. - Số đo trên bản build ngày 26/10 (API trễ 270 ms, desktop): tạo project mới mất khoảng 1,1 s ở CPU 1× và 2 s ở CPU 4×.
- Thứ tự hiện tại: refresh phiên → list/profile →
- Vị trí
- apps/web/src/components/studio/canvas/StudioLauncher.tsx:156, WorkspaceEditorLayout.tsx:12
- Thực hiện
- Đo lại trên
c12a44b, tách thời gian theo từng chặng, rồi mới xử lý từng chặng. Không giấu hoặc dời chỉ báo loading. - Kiểm
- So A/B 3 cặp trên production build: thời gian tới khi Studio dùng được; upload ảnh đầu tiên không chậm đi.
K16FETách EditorSession.tsx (3 223 dòng) và EzWorkspace.tsx (2 460 dòng)
- Vấn đề
- Một component đang ôm cả draft/autosave, reference, upload, chuẩn bị intent, Run, output/history, RAW và handoff EZ → Studio. Sửa một luồng dễ làm hỏng luồng khác. Độ dài file không phải nguyên nhân gây lag.
- Vị trí
- apps/web/src/components/studio/canvas/EditorSession.tsx, apps/web/src/components/customer/EzWorkspace.tsx
- Thực hiện
-
- Tách theo thứ tự: hàm thuần → draft/autosave → reference → upload → chuẩn bị intent → Run → output/history → RAW → phần view.
- Mỗi bước là một PR, giữ nguyên hành vi.
- Giữ key của
EditorSession,useStudioWorkspace,useGenerationvàdraft-read.ts.
- Kiểm
- Mỗi PR có test cho các ca: chuyển ảnh A → B → A, kết quả trả về muộn, double click Run, reload khi đang chạy.
K17FE + CoreTest control → payload cho từng mode
- Vấn đề
-
Chưa có test đi hết chuỗi: control trên UI → intent → schema API → payload provider, cho:
- 6 workflow phòng × 4 mode;
- Topaz: 19 model × 3 quality;
- Multiple Angles và Layer.
- Turbo chỉ có 1K/2K và tối đa 10 ảnh.
- Banana Pro tối đa 8 ảnh, tính cả source và guide.
- Đổi model Topaz phải bỏ các field không tương thích với model mới.
- Vị trí
- apps/web/src/lib/customer/generation.ts:99, studio-settings.ts:23, apps/api/src/core/generation-mode.ts:4
- Thực hiện
- Mỗi cặp workflow/mode một ca chuẩn, thêm các ca ở biên. Tổ hợp không hỗ trợ phải bị chặn trước Run mà vẫn giữ nguyên dữ liệu user.
- Kiểm
- Test offline với fetch bị chặn: payload khớp schema provider (xem trang provider).
K18FE + APIHiển thị từng stage của Layer
- Vấn đề
- Scene có thể xong trước, rồi stage extract hoặc alpha lỗi sau. UI cần giữ scene đã có và báo lỗi riêng của stage đó. Không được báo "không có kết quả", và output đến muộn không được ghi sang ảnh khác.
- Vị trí
- apps/web/src/components/studio/canvas/LayerWorkspace.tsx, apps/api/src/jobs/layer-output.service.ts:415
- Thực hiện
- Dùng fixture có partial output và lỗi ở stage sau để kiểm UI. Nếu API không trả output thì đó là lỗi API, FE không tự đánh dấu là xong.
- Kiểm
- Reload và history vẫn hiện đúng scene; kết quả muộn của ảnh A không xuất hiện ở ảnh B.
K19CoreChưa có bộ ảnh nghiệm thu chất lượng
- Vấn đề
- Job báo thành công chỉ chứng minh có URL, đúng định dạng, số lượng và kích thước. Nó không chứng minh ảnh giữ đúng phòng, đúng đồ, ánh sáng, phối cảnh hay viền alpha.
- Vị trí
services/core-engine/src(compiler, layer-prompts, edit-scope)- Thực hiện
- Lập bộ ảnh input cố định cho mỗi mode/model, kèm tiêu chí chấm. Chạy thật mỗi khi đổi prompt hoặc model.
- Kiểm
- Tỷ lệ output dùng được và tỷ lệ phải chạy lại, theo từng mode.