GraphQL

Field Resolvers & Data Loaders

Optimiser les performances et simplifier l'architecture

Title Text

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin urna odio, aliquam vulputate faucibus id, elementum lobortis felis. Mauris urna dolor, placerat ac sagittis quis.

Title Text

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin urna odio, aliquam vulputate faucibus id, elementum lobortis felis. Mauris urna dolor, placerat ac sagittis quis.

Au programme

  • 🔧 Les Field Resolvers
  • ⚠ ProblĂšmes de l'implĂ©mentation actuelle
  • 📊 Le problĂšme de l'Overfetch
  • 🔗 GraphQL avec REST
  • ⚡ Data Loaders : la solution
  • đŸ—ïž Architecture avant/aprĂšs

Qu'est-ce qu'un Field Resolver ?

  • Fonctions qui rĂ©cupĂšrent les donnĂ©es pour chaque champ
  • RĂ©solution lazy : uniquement si demandĂ©
  • SĂ©paration logique mĂ©tier vs donnĂ©es
@Resolver(() => Cwt)
export class CwtFieldResolver {
  @FieldResolver(() => Document, { nullable: true })
  document(@Root() cwt: Cwt, @Ctx() { dataloaders }) {
    if (!cwt.documentPath) return null;
    return dataloaders.documentLoaders
      .documentPathLoader.load(cwt.documentPath)
  }
  @FieldResolver(() => User, { nullable: true })
  user(@Root() cwt: Cwt, @Ctx() { dataloaders }) {
    if (!cwt.userId) return null;
    return dataloaders.usersLoader
      .getUserLoader.load(cwt.userId)
  }
}

🚹 Problùmes actuels

Use Cases lourds avec couplage fort

// ❌ Ancien code - Use Case lourd
export class GetCwtListUsecase {
  constructor(
    private readonly cwtRepository,
    private readonly mulGateway,        // Dépendance
    private readonly documentGateway    // Dépendance
  ) {}
  async execute(filters) {
    const cwts = await this.cwtRepository.getList(filters)
    // Appels directs aux gateways
    for (const cwt of cwts) {
      cwt.document = await this.documentGateway
        .getDocument(cwt.documentPath)
      cwt.merchant = await this.mulGateway
        .getMerchant(cwt.merchantId)
    }
    return cwts;
  }
}

📊 Le problùme de l'Overfetch

Récupération de données non nécessaires

  • Gaspillage de bande passante
  • Impact nĂ©gatif sur les performances
  • Surcharge inutile des serveurs

REST vs GraphQL

❌ Avec REST

// Frontend demande :
{ id, amount }

// API retourne TOUT :
{
  "id": "123",
  "amount": 1000,
  "documentPath": "/docs/file.pdf",
  "merchantName": "Merchant Corp",
  "beneficiaryDetails": {...},
  "createdAt": "2024-01-01",
  "updatedAt": "2024-01-15"
}

 

REST vs GraphQL

✅ Avec GraphQL

# Frontend demande :
query GetCwtList {
  cwts { id, amount }
}

# GraphQL retourne exactement :
{
  "data": {
    "cwts": [
      { "id": "123", "amount": 1000 }
    ]
  }
}

 

⚠ ConsĂ©quences

  • Use cases surchargĂ©s
  • ProblĂšme N+1
  • Couplage fort
  • Performance dĂ©gradĂ©e

1 requĂȘte liste + N requĂȘtes dĂ©tails = Performance catastrophique

🔗 GraphQL + REST

Pas besoin de tout réécrire !

// DataLoader qui appelle une API REST
class DocumentDataLoader {
  constructor(private restClient: RestClient) {}
  
  async batchLoad(documentPaths: string[]) {
    // Appel REST optimisé en batch
    const response = await this.restClient.post('/documents/batch', {
      paths: documentPaths
    })
    return response.documents
  }
}
Avantages : Migration progressive, APIs conservées, optimisation automatique

⚡ Data Loaders

  • Batching : groupe les requĂȘtes
  • Caching : Ă©vite les doublons
  • Optimisation : rĂ©sout N+1

❌ Sans DataLoader

// N appels individuels
const user1 = await getUserById(1)
const user2 = await getUserById(2)  
const user3 = await getUserById(3)

✅ Avec DataLoader

// 1 seul appel groupé
const [user1, user2, user3] = 
  await userLoader.loadMany([1, 2, 3])

đŸ—ïž Architecture

📊 Diagramme Mermaid ici

AVANT : Use cases lourds → appels directs
APRÈS : Field Resolvers → Data Loaders optimisĂ©s

🎯 BĂ©nĂ©fices

⚡ Performance

  • RĂ©duction N+1
  • Cache intelligent
  • Fetch optimal

🔧 MaintenabilitĂ©

  • SĂ©paration claire
  • Code rĂ©utilisable
  • ÉvolutivitĂ©

🚀 FlexibilitĂ©

  • Queries dynamiques
  • DĂ©couplage
  • Optimisation auto

🎯 RĂ©sumĂ©

Field Resolvers + Data Loaders =
  • ✅ Fin de l'overfetch
  • ✅ RĂ©solution N+1
  • ✅ Use cases simplifiĂ©s
  • ✅ Performances optimales
  • ✅ Compatible REST
GraphQL optimise sans remplacer !

Questions ?

Merci pour votre attention ! 🙏

deck

By Remy Choffardet