discovery-media-player 0.1.93 → 0.1.95

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server/schema.js +31 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discovery-media-player",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
5
5
  "keywords": [
6
6
  "pdf-viewer",
package/server/schema.js CHANGED
@@ -320,25 +320,42 @@ async function vraimentSonderTout() {
320
320
  * Seulement si la colonne est là (sinon la question n'a pas de sens), et JAMAIS bloquant : un
321
321
  * diagnostic ne doit pas casser la carte qu'il enrichit — mieux vaut pas de compteur qu'une carte muette.
322
322
  */
323
+ // Plafond du diagnostic : borné, ET qui le dit. Voir ci-dessous — la borne n'était jamais le défaut,
324
+ // son SILENCE l'était.
325
+ //
326
+ // ⚠️ CONDITION DE VALIDITÉ DE `tronque` : elle ne tient que tant que `PLAFOND_SANS_RANG <= db-max-rows`.
327
+ // Un `limit` explicite NE BAT PAS le plafond implicite du serveur : PostgREST rend `min(limit,
328
+ // db-max-rows)`. Si un exploitant abaisse `db-max-rows` sous ce plafond — durcissement légitime — une
329
+ // liste réellement coupée reviendrait à moins de PLAFOND, `>= PLAFOND` serait faux, et `tronque`
330
+ // redeviendrait un faux négatif SILENCIEUX. C'est le miroir de la leçon des bornes : la PRÉSENCE d'un
331
+ // `limit` n'est pas plus la borne réelle que son ABSENCE n'était « tout ». La détection propre passe par
332
+ // l'en-tête Content-Range, hors de portée de `db.request` (corps seul) — d'où un garde-fou dont on
333
+ // DÉCLARE la condition de validité, plutôt qu'un qu'on croirait inconditionnel. (relevé 2e hôte)
334
+ const PLAFOND_SANS_RANG = 1000;
335
+
323
336
  async function ajouterSansRang(etat) {
324
337
  const r = reponses.get("doc_presentation_messages.mod_seq");
325
338
  if (!r || !r.present) return;
326
339
  try {
327
- // ⚠️ `selectAll`, JAMAIS un `limit` ET C'ÉTAIT LE DÉFAUT DE LA PREMIÈRE VERSION (relevé 2e hôte).
328
- // Un compteur borné qui ne dit pas qu'il est borné redevient le nombre ambigu qu'il remplaçait, et
329
- // une liste tronquée a EXACTEMENT la forme d'une liste complète. Les deux bornes mentaient en sens
330
- // OPPOSÉS : une liste de nuls coupée (l'ordre physique groupe par présentation) pouvait ne voir que
331
- // des scellées total = dontScellees faux « tout va bien » sur une base où des non-scellées ont
332
- // été oubliées ; et la liste de scellées, sans `limit`, tombait sous le plafond IMPLICITE de
333
- // PostgREST (db-max-rows) setScellees incomplet dontScellees sous-compté fausse ALERTE
334
- // permanente sur un hôte à >1000 archives. `selectAll` pagine jusqu'au bout : le transport reste
335
- // borné à la taille RÉELLE du problème (zéro sur un hôte sain), et le compteur ne peut plus mentir
336
- // par troncature. `is.null`/`eq` restent de la syntaxe portable.
337
- const scellees = await PLAYER.db.selectAll("doc_presentations?active=eq.false&control_hash=is.null&select=slug");
338
- const setScellees = new Set((Array.isArray(scellees) ? scellees : []).map((p) => p.slug));
339
- const nuls = await PLAYER.db.selectAll("doc_presentation_messages?mod_seq=is.null&select=slug");
340
+ // ⚠️ BORNÉ, ORDONNÉ, ET QUI DIT QU'IL EST BORNÉ trois défauts corrigés en un (relevé 2e hôte,
341
+ // trois passes). (1) `selectAll` sans borne (0.1.93) : sur un hôte dont le backfill n'a JAMAIS
342
+ // tourné, toutes les lignes sont nulles il paginait la table ENTIÈRE sur la route de la carte,
343
+ // épuisant maxDuration que le try/catch NE rattrape PAS (un dépassement tue la fonction, pas la
344
+ // promesse). La carte TOMBE au lieu de dégrader, ce que la ligne d'à côté interdit. La borne
345
+ // n'était pas le défaut ; son silence l'était. (2) Sans `order=`, la pagination par Range n'a
346
+ // aucune stabilité deux pages doublent ou sautent des lignes sur une base vivante (une
347
+ // présentation en cours EST une base vivante). Les trois autres selectAll du dépôt ont toutes un
348
+ // `order=` ; ce code était le seul à y déroger. (3) On rend donc en UNE requête bornée à PLAFOND,
349
+ // triée, et si la borne est atteinte on pose `tronque: true` : l'égalité total/dontScellees n'est
350
+ // alors plus lisible comme « tout va bien ». Un compteur borné DOIT dire qu'il l'est.
351
+ const bornee = `&order=slug.asc&limit=${PLAFOND_SANS_RANG}`;
352
+ const scellees = await PLAYER.db.request(`doc_presentations?active=eq.false&control_hash=is.null&select=slug${bornee}`);
353
+ const listeScellees = Array.isArray(scellees) ? scellees : [];
354
+ const setScellees = new Set(listeScellees.map((p) => p.slug));
355
+ const nuls = await PLAYER.db.request(`doc_presentation_messages?mod_seq=is.null&select=slug${bornee}`);
340
356
  const liste = Array.isArray(nuls) ? nuls : [];
341
- etat.sansRang = { total: liste.length, dontScellees: liste.filter((m) => setScellees.has(m.slug)).length };
357
+ const tronque = liste.length >= PLAFOND_SANS_RANG || listeScellees.length >= PLAFOND_SANS_RANG;
358
+ etat.sansRang = { total: liste.length, dontScellees: liste.filter((m) => setScellees.has(m.slug)).length, tronque };
342
359
  } catch { /* best-effort : un compteur absent vaut mieux qu'une carte en échec */ }
343
360
  }
344
361