pnpm --filter api db:dev est interactif : il bloque tout appelant non interactif, et l'interrompre laisse un verrou consultatif Postgres qui exige un pg_terminate_backend manuel #63
Closed
opened 2026-09-12 16:32:12 +00:00 by nicolas-fryder
·
2 comments
No Branch/Tag specified
main
dev
@eqs/tooling@0.24.3
@eqs/testing@0.24.3
@eqs/telemetry@0.24.3
@eqs/platform-next@0.24.3
@eqs/platform-nest@0.24.3
@eqs/http@0.24.3
@eqs/errors@0.24.3
@eqs/config@0.24.3
@eqs/cli@0.24.3
@eqs/auth@0.24.3
@eqs/tooling@0.24.2
@eqs/testing@0.24.2
@eqs/telemetry@0.24.2
@eqs/platform-next@0.24.2
@eqs/platform-nest@0.24.2
@eqs/http@0.24.2
@eqs/errors@0.24.2
@eqs/config@0.24.2
@eqs/cli@0.24.2
@eqs/auth@0.24.2
@eqs/tooling@0.24.1
@eqs/testing@0.24.1
@eqs/telemetry@0.24.1
@eqs/platform-next@0.24.1
@eqs/platform-nest@0.24.1
@eqs/http@0.24.1
@eqs/errors@0.24.1
@eqs/config@0.24.1
@eqs/cli@0.24.1
@eqs/auth@0.24.1
@eqs/tooling@0.24.0
@eqs/testing@0.24.0
@eqs/telemetry@0.24.0
@eqs/platform-next@0.24.0
@eqs/platform-nest@0.24.0
@eqs/http@0.24.0
@eqs/errors@0.24.0
@eqs/config@0.24.0
@eqs/cli@0.24.0
@eqs/auth@0.24.0
@eqs/tooling@0.23.0
@eqs/testing@0.23.0
@eqs/telemetry@0.23.0
@eqs/platform-next@0.23.0
@eqs/platform-nest@0.23.0
@eqs/http@0.23.0
@eqs/errors@0.23.0
@eqs/config@0.23.0
@eqs/cli@0.23.0
@eqs/auth@0.23.0
@eqs/tooling@0.22.0
@eqs/testing@0.22.0
@eqs/telemetry@0.22.0
@eqs/platform-next@0.22.0
@eqs/platform-nest@0.22.0
@eqs/http@0.22.0
@eqs/errors@0.22.0
@eqs/config@0.22.0
@eqs/cli@0.22.0
@eqs/auth@0.22.0
@eqs/tooling@0.21.0
@eqs/testing@0.21.0
@eqs/telemetry@0.21.0
@eqs/platform-next@0.21.0
@eqs/platform-nest@0.21.0
@eqs/http@0.21.0
@eqs/errors@0.21.0
@eqs/config@0.21.0
@eqs/cli@0.21.0
@eqs/auth@0.21.0
@eqs/tooling@0.20.0
@eqs/testing@0.20.0
@eqs/telemetry@0.20.0
@eqs/platform-next@0.20.0
@eqs/platform-nest@0.20.0
@eqs/http@0.20.0
@eqs/errors@0.20.0
@eqs/config@0.20.0
@eqs/cli@0.20.0
@eqs/auth@0.20.0
@eqs/tooling@0.19.0
@eqs/testing@0.19.0
@eqs/telemetry@0.19.0
@eqs/platform-next@0.19.0
@eqs/platform-nest@0.19.0
@eqs/http@0.19.0
@eqs/errors@0.19.0
@eqs/config@0.19.0
@eqs/cli@0.19.0
@eqs/auth@0.19.0
@eqs/tooling@0.17.1
@eqs/testing@0.17.1
@eqs/telemetry@0.17.1
@eqs/platform-next@0.17.1
@eqs/platform-nest@0.17.1
@eqs/http@0.17.1
@eqs/errors@0.17.1
@eqs/config@0.17.1
@eqs/cli@0.17.1
@eqs/auth@0.17.1
@eqs/tooling@0.17.0
@eqs/testing@0.17.0
@eqs/telemetry@0.17.0
@eqs/platform-next@0.17.0
@eqs/platform-nest@0.17.0
@eqs/http@0.17.0
@eqs/errors@0.17.0
@eqs/config@0.17.0
@eqs/cli@0.17.0
@eqs/auth@0.17.0
@eqs/tooling@0.16.0
@eqs/testing@0.16.0
@eqs/telemetry@0.16.0
@eqs/platform-next@0.16.0
@eqs/platform-nest@0.16.0
@eqs/http@0.16.0
@eqs/errors@0.16.0
@eqs/config@0.16.0
@eqs/cli@0.16.0
@eqs/auth@0.16.0
@eqs/tooling@0.15.0
@eqs/testing@0.15.0
@eqs/telemetry@0.15.0
@eqs/platform-next@0.15.0
@eqs/platform-nest@0.15.0
@eqs/http@0.15.0
@eqs/errors@0.15.0
@eqs/config@0.15.0
@eqs/cli@0.15.0
@eqs/auth@0.15.0
@eqs/tooling@0.14.0
@eqs/testing@0.14.0
@eqs/telemetry@0.14.0
@eqs/platform-next@0.14.0
@eqs/platform-nest@0.14.0
@eqs/http@0.14.0
@eqs/errors@0.14.0
@eqs/config@0.14.0
@eqs/cli@0.14.0
@eqs/auth@0.14.0
@eqs/tooling@0.13.0
@eqs/testing@0.13.0
@eqs/telemetry@0.13.0
@eqs/platform-next@0.13.0
@eqs/platform-nest@0.13.0
@eqs/http@0.13.0
@eqs/errors@0.13.0
@eqs/config@0.13.0
@eqs/cli@0.13.0
@eqs/auth@0.13.0
@eqs/tooling@0.12.2
@eqs/testing@0.12.2
@eqs/telemetry@0.12.2
@eqs/platform-next@0.12.2
@eqs/platform-nest@0.12.2
@eqs/http@0.12.2
@eqs/errors@0.12.2
@eqs/config@0.12.2
@eqs/cli@0.12.2
@eqs/auth@0.12.2
@eqs/tooling@0.12.1
@eqs/testing@0.12.1
@eqs/telemetry@0.12.1
@eqs/platform-next@0.12.1
@eqs/platform-nest@0.12.1
@eqs/http@0.12.1
@eqs/errors@0.12.1
@eqs/config@0.12.1
@eqs/cli@0.12.1
@eqs/auth@0.12.1
@eqs/tooling@0.12.0
@eqs/testing@0.12.0
@eqs/telemetry@0.12.0
@eqs/platform-next@0.12.0
@eqs/platform-nest@0.12.0
@eqs/http@0.12.0
@eqs/errors@0.12.0
@eqs/config@0.12.0
@eqs/cli@0.12.0
@eqs/auth@0.12.0
@eqs/tooling@0.11.2
@eqs/testing@0.11.2
@eqs/telemetry@0.11.2
@eqs/platform-next@0.11.2
@eqs/platform-nest@0.11.2
@eqs/http@0.11.2
@eqs/errors@0.11.2
@eqs/config@0.11.2
@eqs/cli@0.11.2
@eqs/auth@0.11.2
@eqs/tooling@0.11.1
@eqs/testing@0.11.1
@eqs/telemetry@0.11.1
@eqs/platform-next@0.11.1
@eqs/platform-nest@0.11.1
@eqs/http@0.11.1
@eqs/errors@0.11.1
@eqs/config@0.11.1
@eqs/cli@0.11.1
@eqs/auth@0.11.1
@eqs/tooling@0.11.0
@eqs/testing@0.11.0
@eqs/telemetry@0.11.0
@eqs/platform-next@0.11.0
@eqs/platform-nest@0.11.0
@eqs/http@0.11.0
@eqs/errors@0.11.0
@eqs/config@0.11.0
@eqs/cli@0.11.0
@eqs/auth@0.11.0
@eqs/tooling@0.10.1
@eqs/testing@0.10.1
@eqs/telemetry@0.10.1
@eqs/platform-next@0.10.1
@eqs/platform-nest@0.10.1
@eqs/http@0.10.1
@eqs/errors@0.10.1
@eqs/config@0.10.1
@eqs/cli@0.10.1
@eqs/auth@0.10.1
@eqs/tooling@0.10.0
@eqs/testing@0.10.0
@eqs/telemetry@0.10.0
@eqs/platform-next@0.10.0
@eqs/platform-nest@0.10.0
@eqs/http@0.10.0
@eqs/errors@0.10.0
@eqs/config@0.10.0
@eqs/cli@0.10.0
@eqs/auth@0.10.0
@eqs/tooling@0.9.0
@eqs/testing@0.9.0
@eqs/telemetry@0.9.0
@eqs/platform-next@0.9.0
@eqs/platform-nest@0.9.0
@eqs/http@0.9.0
@eqs/errors@0.9.0
@eqs/config@0.9.0
@eqs/cli@0.9.0
@eqs/auth@0.9.0
@eqs/tooling@0.8.1
@eqs/testing@0.8.1
@eqs/telemetry@0.8.1
@eqs/platform-next@0.8.1
@eqs/platform-nest@0.8.1
@eqs/http@0.8.1
@eqs/errors@0.8.1
@eqs/config@0.8.1
@eqs/cli@0.8.1
@eqs/auth@0.8.1
@eqs/tooling@0.8.0
@eqs/testing@0.8.0
@eqs/telemetry@0.8.0
@eqs/platform-next@0.8.0
@eqs/platform-nest@0.8.0
@eqs/http@0.8.0
@eqs/errors@0.8.0
@eqs/config@0.8.0
@eqs/cli@0.8.0
@eqs/auth@0.8.0
@eqs/tooling@0.7.0
@eqs/testing@0.7.0
@eqs/telemetry@0.7.0
@eqs/platform-next@0.7.0
@eqs/platform-nest@0.7.0
@eqs/http@0.7.0
@eqs/errors@0.7.0
@eqs/config@0.7.0
@eqs/cli@0.7.0
@eqs/auth@0.7.0
@eqs/tooling@0.6.0
@eqs/testing@0.6.0
@eqs/telemetry@0.6.0
@eqs/platform-next@0.6.0
@eqs/platform-nest@0.6.0
@eqs/http@0.6.0
@eqs/errors@0.6.0
@eqs/config@0.6.0
@eqs/cli@0.6.0
@eqs/auth@0.6.0
@eqs/tooling@0.5.1
@eqs/testing@0.5.1
@eqs/telemetry@0.5.1
@eqs/platform-next@0.5.1
@eqs/platform-nest@0.5.1
@eqs/http@0.5.1
@eqs/errors@0.5.1
@eqs/config@0.5.1
@eqs/cli@0.5.1
@eqs/auth@0.5.1
@eqs/tooling@0.5.0
@eqs/testing@0.5.0
@eqs/telemetry@0.5.0
@eqs/platform-next@0.5.0
@eqs/platform-nest@0.5.0
@eqs/http@0.5.0
@eqs/errors@0.5.0
@eqs/config@0.5.0
@eqs/cli@0.5.0
@eqs/auth@0.5.0
@eqs/tooling@0.4.0
@eqs/testing@0.4.0
@eqs/telemetry@0.4.0
@eqs/platform-next@0.4.0
@eqs/platform-nest@0.4.0
@eqs/http@0.4.0
@eqs/errors@0.4.0
@eqs/config@0.4.0
@eqs/cli@0.4.0
@eqs/auth@0.4.0
@eqs/tooling@0.2.0
@eqs/telemetry@0.2.0
@eqs/errors@0.2.0
@eqs/config@0.2.0
@eqs/tooling@0.1.0
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
Infrastructure/eqs-platform#63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ce qui ne va pas
AGENTS.mddu template documente la commande de migration sans dire qu'elle est interactive :Elle mappe sur
prisma migrate dev, qui demande un nom de migration au clavier quand--nameest absent. Un appelant non interactif — un agent de codage, un script, une session sans TTY — se retrouve bloqué sur une invite qu'il ne peut ni voir ni satisfaire. Il n'y a aucune forme non interactive documentée : il faut deviner--name, ce qui est exactement le « montage qu'il a fallu deviner » que le dépôt demande de signaler.Et le mode de sortie est pire que le blocage. Interrompre le processus resté en attente de l'invite laisse le verrou consultatif Postgres de Prisma pris. Toute migration suivante attend indéfiniment ce verrou, sans message expliquant ce qu'elle attend. Il faut alors aller terminer la session côté base à la main :
C'est une opération que personne ne devine à partir du symptôme observé (« la migration ne rend pas la main »), et qui suppose de savoir que Prisma prend un verrou consultatif.
Reproduction
Dans un clone du template, base de développement levée :
Obtenu : la commande attend un nom de migration et ne rend pas la main. Avec un stdin fermé, elle ne peut pas aboutir.
Puis, après interruption :
Obtenu : attente indéfinie sur le verrou consultatif laissé par le processus précédent, sans indication de ce qui est attendu.
Attendu, dans les deux cas : soit une forme non interactive documentée, soit un message qui nomme l'invite et dit comment la contourner — et, sur le second, un message qui dise quel verrou est attendu et comment le lever.
Ce que ça coûte
Bloquant pour tout usage automatisé, et coûteux même en usage humain à cause du second effet.
Le contexte de ce constat rend la chose structurelle plutôt qu'anecdotique : je construis, dans un satellite, un système où des agents écrivent du code et jouent les commandes du socle sans personne devant l'écran. La chaîne de vérification du socle est précisément ce qui rend ce système possible — mais une commande documentée qui attend une frappe au clavier la rend inutilisable telle quelle, et le
AGENTS.mdque l'agent lit ne l'avertit pas.Plus largement :
AGENTS.mdest le document écrit pour des agents. Une commande qu'il recommande sans dire qu'elle est interactive est un piège posé à son lecteur principal.Le coût mesuré ici : un agent bloqué, puis un verrou à lever à la main dans la base, puis la migration rejouée. Une dizaine de minutes pour quelqu'un qui comprend ce qui se passe ; un mur pour quelqu'un qui ne le comprend pas.
Ce que je proposerais
AGENTS.md, puisque c'est le document que les agents lisent :pnpm --filter api db:dev --name <nom_en_snake_case>, en disant que sans--namela commande attend une saisie.db:devexige son nom en argument et échoue en le réclamant, plutôt que d'attendre. Un échec qui nomme ce qui manque vaut mieux qu'une attente muette — c'est déjà la doctrine du socle au démarrage d'une application (plateforme.ts), elle s'applique aussi bien ici.Versions
@eqs/cli,@eqs/tooling,@eqs/testing:^0.8.1.prisma/@prisma/client:^6.16.1.nest, PostgreSQL 18, constaté le 2026-09-12 sur Windows 11 / Docker Desktop.Contournement
Migration rejouée avec
--nameexplicite, après avoir levé le verrou parpg_terminate_backend. Aucun contournement ne subsiste dans le dépôt — mais il subsiste dans les habitudes : tout appelant automatisé de ce dépôt doit désormais savoir qu'il faut passer--name, et ça n'est écrit nulle part dans le socle. C'est ce que ce ticket demande de corriger.refuser-genere.mjsrefuse toutprisma/migrations/**, y compris un squelette--create-onlyjamais appliqué : aucune DDL sur-mesure (trigger, fonction, vue, contrainte) n'est possible par la voie documentée #64Vrai, et votre phrase de conclusion est la meilleure raison de le corriger :
J'ai pris votre option 2 plutôt que la 1, pour la raison que vous donnez vous-même : « un échec qui nomme ce qui manque vaut mieux qu'une attente muette — c'est déjà la doctrine du socle au démarrage d'une application ». Documenter aurait laissé le piège en place pour qui ne lit pas.
db:devrefuse au lieu d'attendreSortie 1, immédiate, stdin fermé. Le message porte les deux conséquences que vous décrivez, pas seulement la première : l'attente, et ce qu'une interruption laisse derrière.
Le script lance le point d'entrée JS de Prisma avec le Node courant, jamais le shim
.cmd— passer par un shell ramèneraitcmd.exe, qui a déjà coûté deux tickets à ce dépôt (#22, #24).Votre option 3 : le verrou
C'est la partie que je trouve la plus utile de votre ticket, parce que personne ne remonte du symptôme à la cause.
AGENTS.mda maintenant sa section :avec la requête
pg_terminate_backend. Et une phrase qui dit pourquoi la section survit à la correction : la commande n'est plus interactive, mais unCtrl+Cau mauvais moment produit le même état.Votre option 4, et ce que je n'ai pas fait
Elle est bonne, et je ne l'ai pas prise — pour une raison que je préfère écrire que taire. Vérifier « ce script attend-il une saisie » demande de jouer chaque script avec stdin fermé. Or les scripts d'un satellite montent des bases, appellent des registres, déploient. Un contrôle qui les lance tous pour voir lesquels bloquent est un contrôle qui fait des dégâts en cherchant.
Il y aurait une forme statique — chercher les commandes connues pour être interactives (
prisma migrate devsans--name,ghsans--yes,npm login) — mais c'est une liste à tenir, et vous connaissez déjà mon avis sur les listes à tenir : le prochain outil interactif repassera par la même case.Si vous voyez une troisième voie, elle m'intéresse. En attendant, la correction structurelle vaut pour ce script-ci, et la remarque est consignée.
Ce que je n'ai pas vérifié moi-même
Je n'ai pas rejoué l'invite ni le verrou : la base de développement du gabarit n'est pas levée sur ce poste, et la monter pour reproduire une interruption de migration coûtait plus que ça ne prouvait. Je me suis appuyé sur votre mesure et sur le comportement documenté de Prisma. Ce que j'ai vérifié, c'est le refus : sortie 1, message complet, stdin fermé.
Branche
fix/migrations-et-db-devsur le gabarit — elle porte aussi #64. Fusionnable tout de suite.minimumReleaseAgeExcluderend toute commandepnpmdépendante du réseau, pas seulement l'installation : aucun satellite ne peut jouer sa porte hors ligne #66Corrigé, côté gabarit.
db:devn'est plusprisma migrate devnu : c'estnode scripts/migrer.mjs, qui traite explicitement le cas non interactif. Son en-tête le dit — « non interactif — un agent de codage, un script, une session sans TTY » — et le message nomme les deux choses qui manquaient : que l'appel reste bloqué, et que l'interrompre laisse le verrou consultatif. Il oriente aussi vers--create-onlyquand c'est un squelette qu'on veut.À rapprocher de #64, qui a ouvert l'autre moitié du chemin :
refuser-generelaisse désormais passer un squelette--create-onlynon suivi par git.Fermé après vérification contre le gabarit à jour le 2026-09-21. Ce ticket restait ouvert faute d'un
Closes #63dans le commit, pas faute de correctif.