Je suis bloqué dans le dev de Tikka quand j’essaie d’utiliser les cursors de Postgraphile sur accounts.transferWithUd.
Et c’est reproductible car inhérent au fonctionnement des cursors.
Je fais une requête des 100 derniers virements de mon compte v1 sur la gtest :
query {
accounts(
filter: {
id:{equalTo: "g1M5PtxdtmkVnaL6GFT94h6FW7MfF2rTfBitVkDtKX2kBTkQL"}
}
) {
nodes {
transferWithUd(
first: 100
orderBy: TIMESTAMP_DESC
) {
nodes {
id
amount
timestamp
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
}
}
}
}
Les cursors en réponse sont :
"pageInfo": {
"hasNextPage": true,
"hasPreviousPage": false,
"startCursor": "WyJuYXR1cmFsIiwxXQ==",
"endCursor": "WyJuYXR1cmFsIiwxMDBd"
},
Les cursors sont des chaînes encodées en base64.
>>> b64decode("WyJuYXR1cmFsIiwxXQ==")
b'["natural",1]'
>>> b64decode("WyJuYXR1cmFsIiwxMDBd==")
b'["natural",100]'
En fait ce sont des offsets déguisés… Vous sentez la douille arriver ?
Maintenant je viens de faire un virement et je veux mettre à jour la liste en récupérant uniquement les virements précédents le startCursor WyJuYXR1cmFsIiwxXQ== :
query {
accounts(
filter: {
id:{equalTo: "g1M5PtxdtmkVnaL6GFT94h6FW7MfF2rTfBitVkDtKX2kBTkQL"}
}
) {
nodes {
transferWithUd(
first: 100
before: "WyJuYXR1cmFsIiwxXQ"
orderBy: TIMESTAMP_DESC
) {
nodes {
id
amount
timestamp
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
}
}
}
}
Résultat vide, ben oui, maintenant le dernier virement a la position de cursor 1, et donc y a rien avant pour Postgraphile :
{
"data": {
"accounts": {
"nodes": [
{
"transferWithUd": {
"nodes": [],
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"startCursor": null,
"endCursor": null
},
"totalCount": 1102
}
}
]
}
}
}
L’IA me propose une solution que voici, ça vous paraît cohérent ?
Je cite :
La vérité sur les curseurs PostGraphile
Ce que tu décris est exact : quand le tri n’est pas basé sur un champ unique et immuable , les curseurs PostGraphile se comportent comme des offsets déguisés .
Pourquoi ?
PostGraphile génère des curseurs qui encodent :
- La valeur du champ de tri (
timestamp)- Un “natural” (position) ou un fallback
Mais si plusieurs enregistrements ont le même timestamp (ou si le tri n’est pas unique), le curseur n’est pas stable . Quand un nouvel enregistrement s’insère avec un timestamp différent, tous les curseurs existants deviennent invalides ou décalés .
C’est exactement ce que tu observes :
- Curseur
["natural",1]→ vide après insertion- Curseur
["natural",2]→ fonctionne (décalé manuellement)C’est un problème connu
PostGraphile utilise
pgsous-jacent, et les curseurs sont basés sur :sql
ORDER BY timestamp DESC, (tableoid, ctid)
Mais
ctidchange avec les insertions/suppressions, donc l’ordre n’est pas stable .2. Ajouter une colonne de tri unique
Si tu peux modifier la base :
sql
ALTER TABLE transfers ADD COLUMN sort_id SERIAL; CREATE INDEX ON transfers (timestamp DESC, sort_id DESC);
Puis trier par
[TIMESTAMP_DESC, SORT_ID_DESC]