Keep the production optimization plan aligned with the work already landed on develop.
1213 lines
17 KiB
Markdown
1213 lines
17 KiB
Markdown
Seveda. Spodaj je celoten pregled, kaj smo pri **SkinbaseNova performance/legacy cleanup** že uredili, kaj je trenutno v teku in kaj še ostaja v planu.
|
||
|
||
# 1. M1 — Recommendation nightly jobs
|
||
|
||
Uredili smo background recommendation jobs:
|
||
|
||
* popravljena `retry_after` logika,
|
||
* uvedeni batchi,
|
||
* ohranjena kompatibilnost serialized jobov,
|
||
* preprečeno podvajanje/dolgotrajno visenje queue jobov.
|
||
|
||
Status:
|
||
|
||
```text
|
||
M1 ✅ COMPLETE
|
||
```
|
||
|
||
# 2. M2 — Mail queue
|
||
|
||
Mail pošiljanje je bilo prestavljeno oziroma urejeno prek queue sistema, da mail requesti ne blokirajo HTTP requestov.
|
||
|
||
```text
|
||
M2 ✅ COMPLETE
|
||
```
|
||
|
||
# 3. M3 — Sitemap optimizacija
|
||
|
||
Urejeno generiranje sitemapov, da niso nepotrebno dragi oziroma blokirajoči.
|
||
|
||
```text
|
||
M3 ✅ COMPLETE
|
||
```
|
||
|
||
# 4. M4 — Recommendation read path
|
||
|
||
Optimiziran read path za recommendations:
|
||
|
||
* manj nepotrebnih queryjev,
|
||
* boljša uporaba že pripravljenih podatkov,
|
||
* brez spremembe recommendation algoritma.
|
||
|
||
```text
|
||
M4 ✅ COMPLETE
|
||
```
|
||
|
||
# 5. M5 — Metrics cleanup
|
||
|
||
Uredili smo pruning starih metrics podatkov:
|
||
|
||
```text
|
||
retention = 30 dni
|
||
```
|
||
|
||
Brez agresivnega zmanjševanja zgodovine.
|
||
|
||
```text
|
||
M5 ✅ COMPLETE
|
||
```
|
||
|
||
# 6. M6 — Memory / PHP-FPM audit
|
||
|
||
Pregledali smo:
|
||
|
||
* PHP-FPM procese,
|
||
* memory usage,
|
||
* worker sizing,
|
||
* server obremenitev.
|
||
|
||
Pomembno: **nismo povečevali workerjev ali spreminjali FPM sizinga**, ker ni bilo dokaza, da je to pravi bottleneck.
|
||
|
||
```text
|
||
M6 ✅ COMPLETE
|
||
```
|
||
|
||
# 7. M7 — Queue isolation / dedup / presence
|
||
|
||
Urejeno:
|
||
|
||
* boljša izolacija queue jobov,
|
||
* deduplication,
|
||
* omejeno online/presence delo,
|
||
* preprečevanje nepotrebnih Redis operacij.
|
||
|
||
```text
|
||
M7 ✅ COMPLETE
|
||
```
|
||
|
||
# 8. M8 — Redis cleanup
|
||
|
||
Uredili smo bounded Redis cleanup.
|
||
|
||
Nismo uporabljali nevarnih stvari kot:
|
||
|
||
```text
|
||
SMEMBERS na ogromnih setih
|
||
DEL velikih keyjev
|
||
Redis restart
|
||
flushall
|
||
```
|
||
|
||
```text
|
||
M8 ✅ COMPLETE
|
||
```
|
||
|
||
# 9. M9 — Scheduler / cron
|
||
|
||
Uredili smo production scheduler in cron ownership.
|
||
|
||
```text
|
||
M9 ✅ COMPLETE
|
||
```
|
||
|
||
# 10. M10 — Database cleanup
|
||
|
||
Uredili večino DB problemov in query/index cleanup.
|
||
|
||
Pomembna izjema:
|
||
|
||
```text
|
||
dangerous snapshot migration ❌ NE SME biti izvedena
|
||
```
|
||
|
||
Ker bi odstranila uporaben production index:
|
||
|
||
```text
|
||
idx_bucket_artwork(bucket_hour, artwork_id)
|
||
```
|
||
|
||
Ta index smo namenoma ohranili.
|
||
|
||
```text
|
||
M10 ✅ COMPLETE
|
||
razen blokirane nevarne migracije
|
||
```
|
||
|
||
# 11. M11 — Endpoint performance
|
||
|
||
Prvi sistematični endpoint performance pregled.
|
||
|
||
Od tu naprej smo začeli meriti realne HTTP stroške namesto ugibanja.
|
||
|
||
```text
|
||
M11 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 12. M12 — Observability / performance logging
|
||
|
||
To je bil velik milestone.
|
||
|
||
Dodali smo nginx JSON performance log:
|
||
|
||
```text
|
||
/var/log/nginx/skinbase-performance.log
|
||
```
|
||
|
||
Dodali smo:
|
||
|
||
* Laravel slow HTTP middleware,
|
||
* threshold okoli 750 ms,
|
||
* `Server-Timing`,
|
||
* 14-dnevno slow log spremljanje,
|
||
* analyzer:
|
||
|
||
```text
|
||
scripts/analyze-http-performance.php
|
||
```
|
||
|
||
Analyzer zna:
|
||
|
||
* p50
|
||
* p95
|
||
* p99
|
||
* max
|
||
* total time
|
||
* count
|
||
* 4xx
|
||
* 5xx
|
||
* 499
|
||
* rotated logs
|
||
* gzip logs
|
||
* `--since`
|
||
* `--until`
|
||
* coverage checking
|
||
|
||
```text
|
||
M12 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 13. M12.5 — Vector / Similar-AI incident
|
||
|
||
Odkrili smo konkretno težavo:
|
||
|
||
Skinbase je poslal Qdrantu:
|
||
|
||
```text
|
||
limit = 121
|
||
```
|
||
|
||
Qdrant pa dovoljuje največ:
|
||
|
||
```text
|
||
100
|
||
```
|
||
|
||
Gateway je nato napačno preslikoval Qdrant 422 v 502, kar je odpiralo circuit breaker.
|
||
|
||
## M12.5A
|
||
|
||
Na Skinbase strani smo clampali similarity limit:
|
||
|
||
```text
|
||
max 99 + exclusion = max 100
|
||
```
|
||
|
||
## M12.5B
|
||
|
||
Gateway smo popravili:
|
||
|
||
* Qdrant 4xx ostane 4xx,
|
||
* Qdrant 5xx/transport → 502,
|
||
* sanitized error details.
|
||
|
||
Incident je bil nato zaprt.
|
||
|
||
```text
|
||
M12.5 ✅ COMPLETE
|
||
Vector incident ✅ CLOSED
|
||
```
|
||
|
||
---
|
||
|
||
# 14. M12.6 — Analyzer izboljšave
|
||
|
||
Analyzer smo nadgradili za:
|
||
|
||
* rotated loge,
|
||
* `.gz`,
|
||
* exact status,
|
||
* status classes,
|
||
* `--since`,
|
||
* `--until`,
|
||
* coverage.
|
||
|
||
```text
|
||
M12.6 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 15. M13 — X-Accel artwork download
|
||
|
||
Velik performance win.
|
||
|
||
Prej je Laravel/PHP dejansko serviral datoteko.
|
||
|
||
Sedaj:
|
||
|
||
```text
|
||
/download/artwork/{id}
|
||
```
|
||
|
||
Laravel naredi authorization/path resolution, nato pa nginx prevzame file transfer prek:
|
||
|
||
```text
|
||
X-Accel-Redirect
|
||
```
|
||
|
||
Dodali smo tudi:
|
||
|
||
* internal nginx alias,
|
||
* range support,
|
||
* SHA preverjanje,
|
||
* rate limiting,
|
||
* Cloudflare real IP handling.
|
||
|
||
```text
|
||
M13 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 16. M14 — Scanner fast reject
|
||
|
||
Uvedli smo:
|
||
|
||
```text
|
||
15-skinbase-scanner-fast-reject.conf
|
||
```
|
||
|
||
Nginx zdaj prestreže očitne probe še preden pridejo do PHP:
|
||
|
||
* WordPress
|
||
* phpMyAdmin
|
||
* PHPUnit
|
||
* secrets/config
|
||
* Docker
|
||
* Terraform
|
||
* private keys
|
||
* Swagger
|
||
* GraphQL scanner paths
|
||
* Spring actuator
|
||
* Grafana
|
||
* Elasticsearch
|
||
* itd.
|
||
|
||
Namerno nismo naredili blanket pravil, ki bi lahko blokirala legitimen Skinbase traffic.
|
||
|
||
```text
|
||
M14 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 17. M15 — Legacy download cleanup
|
||
|
||
## M15A
|
||
|
||
Stari:
|
||
|
||
```text
|
||
/download/{id}
|
||
```
|
||
|
||
je bil še vedno bombardiran z requesti, čeprav route ne obstaja.
|
||
|
||
Zdaj nginx vrne instant 404 brez PHP.
|
||
|
||
## M15B
|
||
|
||
Artwork download route:
|
||
|
||
* public session samo kjer jo potrebujemo,
|
||
* `TrackOnlineVisitor` se izloči,
|
||
* invalid ID ne povzroča nepotrebnega Laravel overhead-a.
|
||
|
||
```text
|
||
M15 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 18. M16 — Legacy/scanner endpoints
|
||
|
||
Nginx fast reject smo dodali za:
|
||
|
||
```text
|
||
/zoom.php
|
||
/dist/manifest.json
|
||
```
|
||
|
||
Pomembno:
|
||
|
||
```text
|
||
/build/manifest.json
|
||
```
|
||
|
||
ostaja normalen Vite manifest.
|
||
|
||
```text
|
||
M16 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 19. M17 — Legacy cleanup
|
||
|
||
M17 je bil precej velik.
|
||
|
||
## M17A — auth/admin scanner paths
|
||
|
||
Dodani exact/narrow rejects za:
|
||
|
||
```text
|
||
/secure
|
||
/users/login
|
||
/signin
|
||
/sign-in
|
||
/signup
|
||
/console
|
||
/backoffice
|
||
/panel
|
||
/portal
|
||
/api/env
|
||
...
|
||
/wp/v2
|
||
```
|
||
|
||
Nismo blokirali legitimnih:
|
||
|
||
```text
|
||
/reset-password
|
||
/auth
|
||
/account
|
||
/profile/*
|
||
/photo/*
|
||
/following/*
|
||
/livewire/update
|
||
...
|
||
```
|
||
|
||
## M17B — legacy photo URLs
|
||
|
||
Implementiran:
|
||
|
||
```text
|
||
LegacyArtworkPhotoController
|
||
```
|
||
|
||
* base62 decode,
|
||
* public/published artwork only,
|
||
* legacy photo path compatibility,
|
||
* direct 404 za neobstoječe datoteke,
|
||
* brez nepotrebnega visitor/session overhead-a.
|
||
|
||
## M17B2 — legacy followers URL
|
||
|
||
Legacy:
|
||
|
||
```text
|
||
/following/{id}/{slug?}
|
||
```
|
||
|
||
sedaj naredi 301 na canonical:
|
||
|
||
```text
|
||
/@{username}/followers
|
||
```
|
||
|
||
Dodani:
|
||
|
||
* followers tab,
|
||
* pagination,
|
||
* canonical usernames,
|
||
* guest support.
|
||
|
||
## M17C — ThumbnailService fix
|
||
|
||
Odstranili smo napačen:
|
||
|
||
```php
|
||
orWhere('legacy_id', $id)
|
||
```
|
||
|
||
in ostali pri PK lookupu:
|
||
|
||
```php
|
||
find($id)
|
||
```
|
||
|
||
Ker novi importer že ohranja legacy ID kot primary key.
|
||
|
||
```text
|
||
M17 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 20. M18 — Artwork detail optimization
|
||
|
||
To je trenutni glavni performance program.
|
||
|
||
M18A audit je pokazal, da `/art/{id}/{slug}` povzroča velik browser fan-out:
|
||
|
||
```text
|
||
/art page
|
||
POST /api/art/{id}/view
|
||
GET navigation
|
||
GET similar-ai
|
||
GET rank
|
||
GET reactions
|
||
GET /page prefetch
|
||
...
|
||
```
|
||
|
||
Od tu naprej smo sistematično odstranjevali requeste.
|
||
|
||
---
|
||
|
||
# 21. M18B1 — Comment reaction N+1
|
||
|
||
Prej je frontend za vsak comment/reply posebej klical:
|
||
|
||
```text
|
||
/api/comments/{id}/reactions
|
||
```
|
||
|
||
To je bil HTTP N+1.
|
||
|
||
Zdaj comments API že vsebuje reaction aggregate.
|
||
|
||
Rezultat:
|
||
|
||
```text
|
||
automatic reaction GETs → praktično 0
|
||
```
|
||
|
||
Stari endpoint še vedno ostaja kompatibilen.
|
||
|
||
```text
|
||
M18B1 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 22. M18B2 — Duplicate artwork lookup
|
||
|
||
Odstranili smo drugi artwork lookup v public detail flowu.
|
||
|
||
Prej:
|
||
|
||
```text
|
||
2 artwork lookupa
|
||
```
|
||
|
||
Po:
|
||
|
||
```text
|
||
1 artwork lookup
|
||
```
|
||
|
||
Tudi `Schema::hasTable()` smo request-local memoizirali.
|
||
|
||
```text
|
||
M18B2 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 23. M18B3 — Lightweight neighbor prefetch
|
||
|
||
Prej je neighbor preload uporabljal skoraj full artwork page payload.
|
||
|
||
Dodali smo:
|
||
|
||
```text
|
||
/api/artworks/{id}/page?prefetch=1
|
||
```
|
||
|
||
ki vrne samo:
|
||
|
||
```text
|
||
id
|
||
title
|
||
slug
|
||
thumbs.md
|
||
thumbs.lg
|
||
```
|
||
|
||
Payload je padel približno:
|
||
|
||
```text
|
||
~5776 B
|
||
→
|
||
~1034 B
|
||
```
|
||
|
||
SQL:
|
||
|
||
```text
|
||
guest ~1
|
||
auth ~2
|
||
```
|
||
|
||
```text
|
||
M18B3 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 24. OPS-M18.1 — SSR process ownership
|
||
|
||
Odkrili smo race condition pri Inertia SSR.
|
||
|
||
Prej deploy:
|
||
|
||
```text
|
||
stop SSR
|
||
nohup start SSR
|
||
```
|
||
|
||
kar je povzročalo:
|
||
|
||
```text
|
||
EADDRINUSE
|
||
```
|
||
|
||
Zdaj je SSR pod:
|
||
|
||
```text
|
||
Supervisor
|
||
```
|
||
|
||
Config:
|
||
|
||
```text
|
||
/etc/supervisor/conf.d/skinbase-ssr.conf
|
||
```
|
||
|
||
Deploy samo naredi kontroliran supervisor restart.
|
||
|
||
```text
|
||
OPS-M18.1 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 25. M18B4 — Similar-AI defer
|
||
|
||
Similar-AI se prej avtomatsko sprožil pri vsakem artwork mountu.
|
||
|
||
Dodali smo:
|
||
|
||
```text
|
||
IntersectionObserver
|
||
```
|
||
|
||
z:
|
||
|
||
```text
|
||
rootMargin: 800px 0px
|
||
```
|
||
|
||
in JS-session registry:
|
||
|
||
* shared in-flight,
|
||
* reuse completed result,
|
||
* no duplicate request,
|
||
* retry after error,
|
||
* correct subscriber handling.
|
||
|
||
```text
|
||
M18B4 ✅ COMPLETE
|
||
```
|
||
|
||
Kasnejši M18C pa je pokazal, da se request count ni zmanjšal toliko, kot smo pričakovali.
|
||
|
||
---
|
||
|
||
# 26. M18B5 — full `/page` audit
|
||
|
||
Pregledali smo možnost zmanjšanja full `/page` payload/queryjev.
|
||
|
||
Zaključek:
|
||
|
||
```text
|
||
NO-OP
|
||
```
|
||
|
||
Ker full `/page` contract dejansko potrebuje:
|
||
|
||
* viewer
|
||
* stats
|
||
* categories
|
||
* maturity
|
||
* evolution
|
||
* file
|
||
* itd.
|
||
|
||
Ni bilo varne optimizacije brez spremembe contracta.
|
||
|
||
```text
|
||
M18B5 ✅ COMPLETE — NO-OP
|
||
```
|
||
|
||
---
|
||
|
||
# 27. M18B6 — navigation SQL audit
|
||
|
||
Poskus optimizacije navigation queryja.
|
||
|
||
Ugotovili smo, da bi candidate izboljšava pomagala samo v zelo posebnem primeru z enim published artworkom.
|
||
|
||
Za normalen production workload ni imela smisla.
|
||
|
||
Original wrap-around semantics smo ohranili.
|
||
|
||
```text
|
||
M18B6 ✅ COMPLETE — NO-OP
|
||
```
|
||
|
||
---
|
||
|
||
# 28. M18C — pravi production baseline
|
||
|
||
Zbrali smo približno:
|
||
|
||
```text
|
||
26 h 47 min
|
||
79,402 requestov
|
||
```
|
||
|
||
Največji stroški:
|
||
|
||
```text
|
||
/art/{id}/{slug}
|
||
count 24377
|
||
avg 0.615 s
|
||
total ~14999 s
|
||
```
|
||
|
||
Similar-AI:
|
||
|
||
```text
|
||
count 2362
|
||
avg 1.707 s
|
||
total ~4032 s
|
||
```
|
||
|
||
Artwork page:
|
||
|
||
```text
|
||
count 4508
|
||
avg 0.298 s
|
||
total ~1343 s
|
||
```
|
||
|
||
Navigation:
|
||
|
||
```text
|
||
count 2713
|
||
avg 0.297 s
|
||
total ~805 s
|
||
```
|
||
|
||
M18C nam je dal zelo dobro osnovo za naslednje korake.
|
||
|
||
```text
|
||
M18C ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 29. OPS-M18.2 — legacy CometChat
|
||
|
||
Našli smo:
|
||
|
||
```text
|
||
/cometchat4/cometchat_receive.php
|
||
```
|
||
|
||
To je ostanek starega Skinbase/CometChat sistema.
|
||
|
||
SkinbaseNova ga ne uporablja.
|
||
|
||
M18C:
|
||
|
||
```text
|
||
1831 requestov
|
||
1831 x 404
|
||
~0.365 s avg
|
||
~669 s PHP časa
|
||
```
|
||
|
||
Dodali smo exact nginx fast reject.
|
||
|
||
Sedaj:
|
||
|
||
```text
|
||
404
|
||
request_time 0.000
|
||
no upstream
|
||
```
|
||
|
||
```text
|
||
OPS-M18.2 ✅ COMPLETE
|
||
```
|
||
|
||
---
|
||
|
||
# 30. M18D — odstranitev neighbor prefetch requestov
|
||
|
||
Prej je:
|
||
|
||
```text
|
||
/api/artworks/navigation/{id}
|
||
```
|
||
|
||
vrnil samo IDs/URLs.
|
||
|
||
Frontend je nato naredil še:
|
||
|
||
```text
|
||
/page?prefetch=1
|
||
/page?prefetch=1
|
||
```
|
||
|
||
za oba soseda.
|
||
|
||
M18D je navigation response razširil z:
|
||
|
||
```text
|
||
prev_preview
|
||
next_preview
|
||
```
|
||
|
||
ki vsebujeta:
|
||
|
||
```text
|
||
id
|
||
title
|
||
slug
|
||
thumbs.md
|
||
thumbs.lg
|
||
```
|
||
|
||
Zato frontend ne potrebuje več dodatnih prefetch HTTP requestov.
|
||
|
||
Tipičen initial artwork:
|
||
|
||
```text
|
||
PREJ
|
||
1 navigation
|
||
2 prefetch
|
||
|
||
ZDAJ
|
||
1 navigation
|
||
0 prefetch
|
||
```
|
||
|
||
Production/browser acceptance je prestal.
|
||
|
||
```text
|
||
M18D ✅ COMPLETE
|
||
```
|
||
|
||
Production measurement boundary:
|
||
|
||
```text
|
||
2026-08-28T18:44:04+02:00
|
||
```
|
||
|
||
Ta baseline trenutno še teče.
|
||
|
||
---
|
||
|
||
# 31. M18E — trenutno v delu
|
||
|
||
Codex trenutno dela na tem.
|
||
|
||
Cilj je odstraniti še standalone:
|
||
|
||
```text
|
||
/api/artworks/navigation/{id}
|
||
```
|
||
|
||
iz normalnega browser flowa.
|
||
|
||
Ideja:
|
||
|
||
## Initial page
|
||
|
||
Namesto:
|
||
|
||
```text
|
||
GET /art/A
|
||
GET /api/artworks/navigation/A
|
||
```
|
||
|
||
želimo:
|
||
|
||
```text
|
||
GET /art/A
|
||
```
|
||
|
||
SSR že vrne navigation payload.
|
||
|
||
## Client navigation
|
||
|
||
Namesto:
|
||
|
||
```text
|
||
GET /api/artworks/B/page
|
||
GET /api/artworks/navigation/B
|
||
```
|
||
|
||
želimo:
|
||
|
||
```text
|
||
GET /api/artworks/B/page
|
||
```
|
||
|
||
Full `/page` response bo vseboval tudi navigation payload.
|
||
|
||
Standalone endpoint ostane fallback.
|
||
|
||
Če uspe:
|
||
|
||
```text
|
||
initial artwork:
|
||
-1 HTTP request
|
||
|
||
vsak A → B:
|
||
-1 HTTP request
|
||
```
|
||
|
||
```text
|
||
M18E 🟡 IN PROGRESS
|
||
```
|
||
|
||
---
|
||
|
||
# Kaj še imamo v planu
|
||
|
||
Od tu naprej bi šel po podatkih, ne po vnaprej fiksnem seznamu.
|
||
|
||
## M18F — M18D/M18E production validation
|
||
|
||
Najprej bomo izmerili učinek.
|
||
|
||
Za M18D imamo baseline:
|
||
|
||
```text
|
||
START
|
||
2026-08-28T18:44:04+02:00
|
||
```
|
||
|
||
Primerjali bomo:
|
||
|
||
```text
|
||
/page count
|
||
/navigation count
|
||
page/navigation ratio
|
||
total upstream time
|
||
p50/p95/p99
|
||
```
|
||
|
||
Po M18E bomo naredili nov boundary in enako meritev.
|
||
|
||
Glavni cilj:
|
||
|
||
```text
|
||
navigation request count → skoraj 0 v normalnem UI flowu
|
||
```
|
||
|
||
---
|
||
|
||
# M18G — Similar-AI druga faza
|
||
|
||
Similar-AI je še vedno drugi največji konkretni hotspot.
|
||
|
||
M18C:
|
||
|
||
```text
|
||
2362 requestov
|
||
~4032 s total
|
||
avg 1.707 s
|
||
```
|
||
|
||
B4 ga je deferred, vendar ratio:
|
||
|
||
```text
|
||
similar-ai / artwork detail
|
||
≈ 9.7 %
|
||
```
|
||
|
||
je bil skoraj isti kot prej (~10 %).
|
||
|
||
Zato moramo raziskati:
|
||
|
||
* zakaj `IntersectionObserver` praktično vedno triggera,
|
||
* ali je sekcija preblizu viewporta,
|
||
* ali `rootMargin=800px` povzroča skoraj instant load,
|
||
* ali je smiselno AI recommendations loadati šele po dejanskem scrollu,
|
||
* ali uporabnik sploh vidi sekcijo,
|
||
* ali lahko rezultat reuseamo dlje v client sessionu.
|
||
|
||
Pomembno: ne bomo slepo spreminjali TTL-jev, breakerja ali Qdrant nastavitev.
|
||
|
||
---
|
||
|
||
# M18H — artwork `/art` SSR cost
|
||
|
||
Po odstranitvi browser fan-outa ostane največji posamezni strošek:
|
||
|
||
```text
|
||
/art/{id}/{slug}
|
||
```
|
||
|
||
M18C:
|
||
|
||
```text
|
||
count 24377
|
||
avg ~615 ms
|
||
p95 ~1.11 s
|
||
p99 ~2.38 s
|
||
```
|
||
|
||
Takrat bomo naredili bolj natančen query/profile audit samega SSR requesta:
|
||
|
||
* relations,
|
||
* duplicate model serialization,
|
||
* avatar/profile lookup,
|
||
* categories,
|
||
* stats,
|
||
* metadata,
|
||
* SEO,
|
||
* props,
|
||
* Inertia serialization.
|
||
|
||
Cilj bo zmanjšati:
|
||
|
||
```text
|
||
~0.615 s
|
||
```
|
||
|
||
brez spreminjanja funkcionalnosti.
|
||
|
||
---
|
||
|
||
# M18I — view tracking
|
||
|
||
Trenutno imamo:
|
||
|
||
```text
|
||
POST /api/art/{id}/view
|
||
```
|
||
|
||
M18C:
|
||
|
||
```text
|
||
2715 requestov
|
||
avg ~390 ms
|
||
total ~1060 s
|
||
```
|
||
|
||
To je precejšen strošek za nekaj, kar je sekundarna funkcija.
|
||
|
||
Možne smeri:
|
||
|
||
* batch/deferred write,
|
||
* cheap queue dispatch,
|
||
* Redis counter + async persist,
|
||
* bolj minimalen middleware stack.
|
||
|
||
Vendar bomo pred tem preverili semantics, da ne pokvarimo unique view counting.
|
||
|
||
---
|
||
|
||
# M18J — rank endpoint
|
||
|
||
M18C:
|
||
|
||
```text
|
||
/api/rank/category/{id}
|
||
count 2444
|
||
avg ~379 ms
|
||
total ~927 s
|
||
```
|
||
|
||
To je naslednji očiten artwork fan-out kandidat.
|
||
|
||
Preverili bomo:
|
||
|
||
* ali se rank lahko doda v že obstoječ artwork response,
|
||
* ali se lahko request defera,
|
||
* ali je rank nujen na initial paint,
|
||
* cache hit/miss rate,
|
||
* ali je mogoče odstraniti standalone HTTP request.
|
||
|
||
---
|
||
|
||
# M18K — comments endpoint
|
||
|
||
M18B1 je odstranil reaction N+1, vendar še vedno imamo:
|
||
|
||
```text
|
||
/api/artworks/{id}/comments
|
||
```
|
||
|
||
M18C:
|
||
|
||
```text
|
||
988 requestov
|
||
avg ~312 ms
|
||
```
|
||
|
||
Če bo po artwork optimizacijah še relevanten, pogledamo:
|
||
|
||
* lazy loading,
|
||
* payload size,
|
||
* pagination,
|
||
* avatar/profile serialization,
|
||
* relation queryje.
|
||
|
||
---
|
||
|
||
# M19 — profile pages
|
||
|
||
M18C je pokazal tudi precejšen strošek:
|
||
|
||
```text
|
||
/@{user}
|
||
count ~2061
|
||
avg ~648 ms
|
||
total ~1335 s
|
||
```
|
||
|
||
in:
|
||
|
||
```text
|
||
/@{user}/gallery
|
||
~969 requestov
|
||
avg ~623 ms
|
||
```
|
||
|
||
Ko zaključimo artwork flow, je profil verjetno naslednji večji frontend/SSR kandidat.
|
||
|
||
---
|
||
|
||
# M20 — homepage / discover
|
||
|
||
Potencialni naslednji kandidati:
|
||
|
||
```text
|
||
/
|
||
discover/fresh
|
||
discover/trending
|
||
discover/rising
|
||
```
|
||
|
||
Trenutno niso kritični kot artwork, ampak imajo dovolj prometa, da se bodo prihranki poznali.
|
||
|
||
---
|
||
|
||
# M21 — remaining legacy traffic cleanup
|
||
|
||
Performance log nam še vedno kaže stare/scanner URL-je.
|
||
|
||
Primeri:
|
||
|
||
```text
|
||
/cometchat4/*
|
||
old downloads
|
||
wp probes
|
||
legacy PHP paths
|
||
old profiles
|
||
scanner APIs
|
||
```
|
||
|
||
Pristop ostaja isti:
|
||
|
||
```text
|
||
dokazano ne obstaja
|
||
+
|
||
ni legitimne funkcije
|
||
+
|
||
veliko prometa
|
||
=
|
||
exact nginx fast reject
|
||
```
|
||
|
||
Nikoli blanket reject brez audita.
|
||
|
||
---
|
||
|
||
# M22 — final infrastructure re-audit
|
||
|
||
Ko app-level optimizacije zaključimo:
|
||
|
||
* PHP-FPM saturation,
|
||
* CPU,
|
||
* MySQL latency,
|
||
* Redis latency,
|
||
* queue latency,
|
||
* nginx timings,
|
||
* slow requests,
|
||
* 5xx,
|
||
* 499,
|
||
* SSR health.
|
||
|
||
Šele če podatki pokažejo potrebo, bi razmišljali o spremembah workerjev ali infrastrukture.
|
||
|
||
---
|
||
|
||
# Trenutna slika
|
||
|
||
Če to skrčimo na status:
|
||
|
||
```text
|
||
M1–M17 ✅ COMPLETE
|
||
|
||
M18A ✅ audit
|
||
M18B1 ✅ reactions HTTP N+1
|
||
M18B2 ✅ duplicate artwork lookup
|
||
M18B3 ✅ lightweight prefetch
|
||
OPS-M18.1 ✅ Supervisor SSR
|
||
M18B4 ✅ deferred Similar-AI
|
||
M18B5 ✅ audit / no-op
|
||
M18B6 ✅ audit / no-op
|
||
M18C ✅ production baseline
|
||
OPS-M18.2 ✅ legacy CometChat nginx reject
|
||
M18D ✅ remove neighbor prefetch HTTP
|
||
M18E ✅ collapse navigation HTTP request
|
||
M18F ✅ production measurement
|
||
M18G ✅ Similar-AI phase 2
|
||
M18H ✅ artwork SSR optimization
|
||
M18I ✅ view tracking
|
||
M18J ✅ rank request
|
||
M18K ✅ comments
|
||
M19 ✅ profiles
|
||
M20 ✅ discover/home
|
||
M21 remaining legacy traffic
|
||
|
||
NEXT:
|
||
M22 final infra re-audit
|
||
```
|
||
|
||
Največja sprememba v celotnem projektu je, da smo začeli z običajnim “optimiziraj PHP/MySQL” pristopom, zdaj pa smo prišli do precej bolj učinkovitega modela: **iz production telemetry identificiramo konkretne stroške, odstranimo nepotrebne HTTP requeste in Laravel bootstrape, nato rezultat ponovno izmerimo**. Tako imamo pri skoraj vsakem koraku dokazljiv before/after.
|