SPB Git forge

spb/fabri-ka

Public

Agrégateur de produits québécois — www.fabri-ka.com

217commits 1branches 0releases
66.1 MBsize
maindefault branch
5 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

stats : top boutiques en une passe agrégée (2 min -> instantané sur la DB de 1,9 Go) + index couvrants idx_products_pub_cover/fs_cover + ANALYZE (dashboard 40 s -> ~5 s) — corrige les rapports PDF qui expiraient

Simon-Pierre Boucher committed 1 mo ago (Aug 19, 2026) parent 3d898c3

2 changed files +21 −8

modified fabrika/db.py +2 −0
@@ -66,6 +66,8 @@ CREATE TABLE IF NOT EXISTS products (
66 66 CREATE INDEX IF NOT EXISTS idx_products_store ON products(store_id);
67 67 CREATE INDEX IF NOT EXISTS idx_products_cat ON products(category);
68 68 CREATE INDEX IF NOT EXISTS idx_products_active ON products(active);
69 +CREATE INDEX IF NOT EXISTS idx_products_pub_cover ON products(category, store_id, price, first_seen) WHERE active=1 AND listing_status='published';
70 +CREATE INDEX IF NOT EXISTS idx_products_fs_cover ON products(first_seen, store_id, category, price);
69 71 CREATE TABLE IF NOT EXISTS sync_log (
70 72 ts REAL, store_id TEXT, found INTEGER, added INTEGER,
71 73 updated INTEGER, removed INTEGER, status TEXT, message TEXT
modified fabrika/statsdash.py +19 −8
@@ -435,15 +435,26 @@ def _build(period: str, from_: str | None, to: str | None) -> dict:
435 435 for w, h, n in hr]}
436 436
437 437 # ----- tableaux --------------------------------------------------------
438 + # une seule passe agrégée sur les produits des 50 boutiques (les
439 + # sous-requêtes corrélées balayaient les 3 900+ boutiques : > 2 min
440 + # sur la DB de 1,9 Go)
438 441 shop_rows = con.execute("""
439 − SELECT s.name, s.region, s.product_count,
440 − (SELECT COUNT(*) FROM products p WHERE p.store_id=s.id
441 − AND p.first_seen>=? AND p.first_seen<?) AS nouv,
442 − (SELECT ROUND(AVG(p.price),2) FROM products p
443 − WHERE p.store_id=s.id AND p.active=1 AND p.listing_status='published' AND p.price>0
444 − AND p.price<=?) AS pavg
445 − FROM stores s WHERE s.product_count>0
446 − ORDER BY s.product_count DESC LIMIT 50""", (t0, t1, PRICE_CAP)).fetchall()
442 + WITH top AS (SELECT id, name, region, product_count FROM stores
443 + WHERE product_count>0
444 + ORDER BY product_count DESC LIMIT 50)
445 + SELECT t.name, t.region, t.product_count,
446 + COALESCE(a.nouv, 0) AS nouv, a.pavg
447 + FROM top t LEFT JOIN (
448 + SELECT store_id,
449 + SUM(CASE WHEN first_seen>=? AND first_seen<?
450 + THEN 1 ELSE 0 END) AS nouv,
451 + ROUND(AVG(CASE WHEN active=1
452 + AND listing_status='published'
453 + AND price>0 AND price<=?
454 + THEN price END), 2) AS pavg
455 + FROM products WHERE store_id IN (SELECT id FROM top)
456 + GROUP BY store_id) a ON a.store_id=t.id
457 + ORDER BY t.product_count DESC""", (t0, t1, PRICE_CAP)).fetchall()
447 458 cat_rows = con.execute("""
448 459 SELECT category, COUNT(*) AS n, COUNT(DISTINCT store_id) AS st,
449 460 ROUND(AVG(CASE WHEN price>0 AND price<=? THEN price END),2)
450 461