Questions GraphQL et la RFC pour l'APi GVA

Pour la pagination, nous pourrions aussi la rendre optionnelle en argument, mais que le noeud en applique une par défaut.
C’est ce que fait par exemple ElasticSearch, avec a chaque réponse l’ajout d’un total.

1 Like

Il serait bon également de fixer un maximum au nombre d’élément renvoyé (la taille attendue de la pagination).
Par exemple 1000.

1 Like

Ce comportement est “implicite” pas “explicite”. En lisant le code du client, on ne saura pas quelle valeur le serveur renvoie par page.

input Paging {
  pageNumber: Int! = 0
	pageSize: Int! = 50
  fromBlock: Int! = 0
  # If toBlock is null, current block number is used
  toBlock: Int
}

@elois, si l’argument Paging est obligatoire et son champ pageSize aussi, alors pourquoi donner une valeur par défault ? Dans ce cas, la valeur maximum est gérée par le code du serveur, non ?

Tu as sûrement déjà du trouver la réponse, mais j’ai trouvé ceci (oui dans les specs, pas toujours dans les implémentations, gaffe !) :

@cgeek @Junidev @vit @Inso @kimamila j’ai pushé une v2 du schéma ici tenant compte d’une partie de vos retours.

J’ai quelques et remarques sur vos retours :

Est il possible de définir en une seule fois un type qui sera a la fois un input et a la fois un type de retour ? Ça permettrait de ne plsu dupliquer la déclaration du blockstamp (renommé BlockNumberAndHash) ?

@vit la valeur par défaut est la pour donner plus de souplesse aux dev d’app tierces et ne pas leur imposer de renseigner tout les champs de Paging. Le seul champ a renseigner est toBlock, et il peut etre renseigné a null :slight_smile:

Étant donné que toutes les implémentations de Duniter devront fournir gva il me semble préférable que l’on n’utilise pas de feature avancée de graphql qui ne seraient pas présentent dans toutes les implémentations de GraphQL. Typiquement pas d’input par défaut, ni de directive :slight_smile:

C’est un choix possible mais comme le dit @vit c’"est le serveur qui fixera ces valeurs par défaut, indépendamment de ce qu’il y a dans le schéma, je préférerai que les valeurs par défaut apparaissent dans le schéma de sorte a ce que la seule vue du schéma permette de connaître les valeurs par défaut :slight_smile:

Pour moi ça ne peut pas etre un argumen, du schéma, c’est dans le code du serveur que se trouvera la limitation, on peut néanmoins indiquer en commentaire du schéma que la taille maximale d’une page est de 500 (je pensais plus a 500 qu’a 1000).

Il faudrait ajouter peut-être des “filters”, pour filtrer les listes :

input AssetFilter {
  AND: [AssetFilter!]
  OR: [AssetFilter!]
  createdAt: DateTime
  createdAt_not: DateTime
  createdAt_in: [DateTime!]
  createdAt_not_in: [DateTime!]
  createdAt_lt: DateTime
  createdAt_lte: DateTime
  createdAt_gt: DateTime
  createdAt_gte: DateTime

mais surtout des “orderBy” (attention exemple bourrin avec sens du tri collé à la colonne du tri):

enum AssetOrderBy {
  createdAt_ASC
  createdAt_DESC
  fileName_ASC
  fileName_DESC
  handle_ASC
  handle_DESC
  height_ASC
  height_DESC
  id_ASC
  id_DESC
  mimeType_ASC
  mimeType_DESC
  size_ASC
  size_DESC
  updatedAt_ASC
  updatedAt_DESC
  url_ASC
  url_DESC
  width_ASC
  width_DESC
}

Voir https://swapi.graph.cool/

Le but n’est évidemment pas de faire des requêtes trop complexes dans GVA, il y a les serveurs ES pour des besoins plus complexes et des réponses plus rapides.

1 Like

Ok @vit est ce que tu veut ajouter toi des “filters” au schéma ? Ou tu préfère que je le fasse ?

Pour le tri, ce que je vois généralement c’est plutôt un simple “sortAttribute” et “sortSide”.
Sachant que les attributs du type “nested.attribue” pour atteindre des champs fils.
On peut aussi faire simple et ne permettre les tri que sur les premiers niveaux

La dessus faut voir. Si tous les clients ont encore besoin d’API supplémentaire il me semble que ça réduit l’intérêt de GVA…

1 Like

Oui c’est plus simple en effet :slight_smile:
Concrètement “sortAttribute” et “sortSide” seraient des input de type String (en term de type graphQL j’entend, je sais bien que derrière tout est string :wink: )?

Je vais faire une POC asap avec Duniterpy, mais dans mon esprit embrumé je vois quelque chose comme :

  • Requête des peers pour trouver une majorité de concensus afin de définir la blockchain “majoritaire”.
  • Chercher parmi les serveurs ES connus celui qui est sur la bonne branche.
  • Faire les plus grosses requêtes sur lui.

Donc :

  • Ecriture (database normalisée) sur les noeuds via una API propre et standard GVA + quelques requêtes de lecture de base (documentation par introspection).
  • Lecture ultra rapide à partir de documents dénormalisés (NoSql) sur serveur ES.

GVA est nécessaire surtout en écriture, mais n’égalera jamais ES pour la lecture. Donc restons simple.

Cool merci beaucoup :slight_smile:

Pour connaître le consensus réseau il est beaucoup plus pertinent de requeter les heads qui sont mis a jour a chaque block, alors que les ficher de peer sont mise a jours moins souvent. De plsu ce n’et pas leur role, elles sont faite pour découvrir le réseau, pas pour savoir la branche sur laquelle se’ trouve chaque noeud, cgeek a créer les HEADs exprès dans cet but, utilisons les :slight_smile: (Je vais rajouter les requetes des peeers et heads dans le schéma, j’ai pas encore pris le temps de le faire).

Duniter est passé en NoSql avec LevelDB, et Durs est aussi en NoSql avec rustbreak, il faudra faire des bench tests mais il est tout a fait possible et même probable que ça puisse rivaliser avec un serveur ES :slight_smile: (si cela s’avérait les serveurs ES ne serait pas indispensable, ce que semble souhaiter benoit)

Alors là j’ai un gros doute, et je ne comprends plus très bien pourquoi on ferait un schéma simple, si vous voulez que GVA remplace ES.

GVA ne remplacera jamais ES, amha, en terme de facilité à faire des requêtes complexes d’une part, et je doute fortement qu’un simple module nosql puisse répondre, lors d’une recherche complexe sur plusieurs millions d’'éléments, en dessous des 20 ms. Ce que peut faire allègrement ES.

Je pense qu’il faut que l’on ce concerte là, pour se mettre d’accord sur ce que les développeurs de clients (prioritairement) veulent pouvoir faire avec GVA d’une part et avec ES d’autre part.

@vit je ne veut pas que GVA remplace “ES”, je crois que c’est juste un malentendu sur les besoins :sweat_smile:

Je n’utilise pas ES, et je ne percevais pas que ça faisait parti du sujet. De plus graphql n’impose pas de DB particulière, on peu très bien faire du ES derrière du graphql :wink:

Pour moi le principal intérêt de GrapQL c’est d’avoir une API facile a utilisée par des dev d’app tierces, donc je préfère qu’on parte sur un schéma pas trop complexe.

Si certaines app ont besoin de performances très accrues sur des types de requêtes très spécifiques ça peut devenir pertinent de leur dédié une API spéciale, mais GVA a plus un rôle d’API généraliste d’entrée dans l’éco-système duniter :slight_smile:

EDIT: pour une fois je suis tout a fait d’accord avec @Junidev, preuve que je juge les idées et pas les personnes :wink:

Je n’ai lu que ta réponse, l’autre je ne le lis plus.

ES est surtout une API très complète, pour accéder à une DB nosql Lucène améliorée. (j’ai fait mumuse avec au boulot).

Faire du GraphQL sur du ES ? Et se priver des filtres et requêtes imbriquées ? Quelle drôle d’idée ? :wink:

Moi, je bosse sur les clients (Duniterpy et Sakia) et j’ai besoin d’une api/db qui poutre. ES est un très bon candidat, surtout depuis que @kimamila a développé la synchro avec les nœuds Duniter et le p2p entre nœuds ES (je crois)…

Après avoir utilisé BMA, qui n’avait pas prétention à servir tous les besoins client (d’où la souffrance des dev clients sur la wot ou les historiques), si on recode les clients, je ne veux pas me lancer sur une API avec encore des limitations. Donc une GVA basique pour l’envoie des documents et détecter les heads (merci pour l’info :grin: ) me suffit, mais j’utiliserai ES pour les requêtes lourdes (historiques et la wot).

C’est ma roadmap pour Duniterpy, et dont Sakia et Silkaj pourront profiter.
Ce qui finalement ne contredit en rien ce qui est en train d’être fait pour GVA. :grinning:

Alors je suis globalement d’accord avec l’analyse, mais je voudrais juste rappeler quelquechose.

Ce qui coute cher pour Cesium & Sakia, ce n’est pas vraiment le temps de la requête (qui a toujours été suffisamment rapide même en BMA). C’est l’overhead induit par le HTTP et la multiplicté des requêtes. Ce que GVA doit chercher à régler, c’est avant tout la nécessité de multiplier les requêtes.

Dans le monde idéal, lorsqu’on affiche un nouvel écran dans le client :

  • On exécute une seule requête pour la totalité de l’écran vers un noeuds
  • On exécute N requêtes de vérification pour la totalité de l’écran vers N noeuds

Ca fait N+1 requête en parallèle seulement par écran (N étant le degré de vérification). Alors qu’on aujourd’hui, avec REST, c’est une requête par information souhaitée. Pour une identité, on aboutit à une dizaine requête (que du coup on ne valide pas car sinon ça couterait trop cher dans Cesium).

2 Likes

Merci @inso pour ces précisions !

Ce que je recherche moi, c’est répondre au besoin des clients, quelque soit ce besoin.
Ok Ok les index c’est rapide… Même si j’attends des benchmarks sur vos requêtes :wink:

Si GVA arrive à égaler ES en terme de simplicité à construire des requêtes complexes et en terme de temps de réponse, moi je ne demande que ça ! Mais alors on ne peut pas se contenter d’un schéma basique. Il faudra un schéma mega puissant répondant à tous les besoins clients.

Donc ce qui resterait à améliorer :

  • Lourdeur du transport HTTP : on peut normalement utiliser d’autres protocoles d’échange, puisque GraphQL n’est pas lié au protocole HTTP contrairement à REST. Appolo supporte le transport Wesocket mais Urql aussi ! Protocole de transport rapide fait maison ou trouvé sur le net avec une forte communauté ?

  • Requêtes multiples en une requête : ça fonctionne très bien, j’ai testé, et j’ai découvert aussi un mode batch qui agrège les réponses de plusieurs requêtes distinctes en une seule réponse.

  • Facilité de construire des requêtes complexes avec filtres (IN (id1,id2) OR date > xx-xx-xxxx AND < xx-xx-xxx) : reproduire la facilité de faire des requêtes complexes comme dans ES. Cela requiert pour moi un schema complexe, avec une grammaire pour les filtres, pas juste un schéma basique.

  • Aggréger de multiples schémas en un seul : si on veut garder un schéma basique facile à implémenter dans tous les langages, complété par un ou plusieurs schéma plus complet, on peut aggréger des schémas GraphQL.

D’autres atouts de GraphQL ici :

En codant de nouvelles requêtes p2p dans Duniterpy, j’aurais un aperçu réel des capacités de GVA, et je pousserai pour améliorer tant qu’il le faudra cette API jusqu’à ce qu’elle réponde au mieux aux besoins des clients.

2 Likes

Je n’ai jamais parlé de remplacé ES, si ? Je pensais qu’on remplaçait BMA… Ou alors je comprend rien…
Aujourd’hui Cesium-plus-pod n’est pas indispensable a Césium : seul BMA est indispensable.
De mon point vue, il faut sue les clients puisse puissent fonctionner dans rien d’autre (pour les fonctions de base).
Cela n’empêchera pas les clients d’utiliser d’autres services en lignes.

En fait, de mon côté j’envisage ensuite de rendre les pods Cs+ avec GVA. J’ai commencé a le faire avec BMA.
Seul les perfs changeront (ou pas). Certaines requêtes seront déléguées au noeud (Dunite) sous-jacent.
Bref, il ne faut pas tenir compte de ce que fait ou pas ES. Je le citais uniquement vis à vis de sa pagination par défaut, etc.

Attention la il y a une incompréhension : Césium n’exploite que BMA pour toutes les données, sauf les graphiques, les profiles, les messages qui sont toutes des choses optionnelles.
Pour le moment, même si je pourrais remplacé des requêtes au noeuds Duniter par des accès ES, je ne l’ai pas codé.
En revanche, j’ai commencé a implémenté BMA sur les pod Cs+ pour avoir de meilleurs perfs.

Dis autrement, les perfs de Cesium ne sont pas terribles (je trouve) car BMA via les noeuds est lent.
Si j’avais que des accès ES pour la lecture, ce serait beaucoup plus rapide, c’est sur !
(C’est en cours, donc je peux déjà confirmer !)

J’ai édité mon précédent message avec les propositions de ce qu’il est possible et souhaitable de faire avec GraphQL.

Si je résume les pensées de chacun, on partirait sur :

  • Un schéma minimal reproduisant les fonctionnalités indispensable de BMA et devant être présent dans toutes les implémentations.
  • Des schémas optionnels plus complexes reproduisant certaines fonctionnalités plus avancées, certaines uniquement possibles actuellement via un pod ES.
  • Un protocole de transport plus rapide que HTTP, si simple à implémenter, à voir.

Le but est d’obtenir la richesse des requêtes et la vitesse de réponse de ES dans GVA.

La vitesse passera aussi par une bonne gestion des indexes dans les databases pour chaque implémentation.

Veuillez mettre un like si vous êtes ok pour cette “pseudo” roadmap.
Sinon expliquez vos remarques en réponse (ou autour d’une bière aux prochaines RML). :wink:

1 Like