Sconti Nova
Offerte Amazon verificate ogni ora. Costruito con un socio.
Codice disponibile su richiesta

Il problema
I siti di offerte invecchiano in fretta: i prezzi cambiano, i coupon scadono e lo stesso prodotto compare tre volte da tre fonti. Sconti Nova importa offerte da un canale Telegram e da Amazon stessa, verifica ogni prezzo su Amazon prima di mostrarlo e tiene una sola scheda per ogni offerta reale.
- Stato
- Online, con un ciclo del catalogo ogni ora
- Stack
- Next.js 16, React 19, TypeScript, Tailwind 4, Supabase, PostgreSQL, Vercel Cron, Tiptap, Vitest, Playwright
- Facts
- 75 file di test, compresi test del database su PGlite
- 29 migrazioni
- Controlli di accessibilità con axe nei test end-to-end
Le scelte che vale la pena spiegare
Due fonti non possono creare due volte la stessa offerta
Telegram e Amazon alimentano entrambi il catalogo. Prima di inserire, la ricerca prende un advisory lock di transazione sull’ASIN del prodotto, così due importazioni contemporanee non possono decidere entrambe che la scheda manca. Il lock sta nelle funzioni di salvataggio, quindi copre anche il ciclo orario.
Stesso prodotto non vuol dire stessa offerta
Due offerte si uniscono solo se variante, accesso Prime, quantità, coupon, codice, venditore e limiti d’acquisto coincidono tutti. Un nome simile non prova niente, e un venditore sconosciuto non viene mai considerato uguale a un altro.
Il ciclo orario resiste a timeout e doppioni
Ogni ora di lavoro è una riga con un proprietario, un lease e un fencing token. Ogni blocco gira in una richiesta serverless con un budget di tempo e scrive un checkpoint, e un worker superato il cui fence è cambiato non può più scrivere. Se l’ora finisce, il riepilogo dice parziale, mai completato.
Un pezzo del codice
Il lock si prende prima della ricerca, così controllo e inserimento non possono essere separati da un’altra importazione.
-- Separate commands after the lock give the lookup a fresh Read Committed snapshot.
create function nova_catalog.find_verified_product(p_asin text,p_conditions jsonb,p_preferred_id uuid default null)
returns uuid language plpgsql volatile security invoker set search_path='' as $$
declare pid uuid;
begin
if p_asin is null or p_asin !~ '^[A-Z0-9]{10}$' then return null; end if;
perform pg_catalog.pg_advisory_xact_lock(pg_catalog.hashtextextended('sconti-nova:verified-offer:'||p_asin,0));
-- An unknown seller is not evidence that two commercial offers are equal.
if jsonb_typeof(p_conditions) is distinct from 'object' or nullif(p_conditions->>'merchantId','') is null then return null; end if;
select p.id into pid from public.products p
where p.verified_asin=p_asin and (p.catalog_source_offer_id is not null or p.catalog_discovery_id is not null)
and nova_catalog.product_verified_conditions(p)=p_conditions
order by (p.id=p_preferred_id) desc nulls last,p.created_at asc,p.id asc
limit 1 for update of p;
return pid;
end $$;