Pagination – Récupérer tous les dossiers d'une démarche
Exemple de cas d'usage : votre démarche est aujourd'hui close et vous souhaitez récuperer les informations des dossiers pour faire de l'analyse de donnée.
Avez-vous pris connaissance de notre mechanisme de pagination ?
Pour paginer vos requetes, il faut ajouter les curseurs à votre requete GraphQL, Pour ce faire ajouter le PageInfoFragment et déclarez les variables de pagination sur la ressource paginée Ex :
Pour faciliter la lecture du code, la query GraphQL est fournie en PJ
Ensuite, vous pouvez executer ce code ruby qui :
cherche a retrouver le dernier curseur que vous avez utiliser
si il est présent, le ré-utilise pour requeter la page suivante (sinon il repart a 0)
requete la page
sauve le curseur
Vous pouvez ainsi executer le script plusieurs fois pour parcourir toutes les pages de dossier de votre démarche
poller.rb
require'net/http'require'uri'require'json'ENDPOINT=URI('https://www.demarches-simplifiees.fr/api/v2/graphql')CURSOR_STORAGE='lastCursor'EMPTY_CURSOR= {}### that's the GraphQL part.# We store the query in a flat file because it's easier to readdefqueryFile.read("getDemarche.samplePagination.graphql")end### that's the cursor / pagination part.# We store the cursor in a .json file because it's easier for the demo# Each demarche can have it's own cursor for continuous/batch pollingdefcursor_file_path(demarche_number)"#{EMPTY_CURSOR}-#{demarche_number}.json"end# when we emit a request, we try to reuse last persisted cursordefretrieve_last_persisted_cursor(demarche_number) JSON.parse(File.read(cursor_file_path(ENV.fetch('DEMARCHE_NUMBER') { raise 'missing env var DEMARCHE_NUMBER' }))) || {}
rescueErrno::ENOENT# first call, file was never writtenputs"Info: first time using cursor on #{demarche_number}"EMPTY_CURSORrescueJSON::ParserError# strange parse errorputs"Warning: strange case, check your cursor data"EMPTY_CURSORend# when we receive a response, we try keep the cursor for next calldefpersist_last_cursor(response, demarche_number) cursor = response.dig("data","demarche","dossiers","pageInfo")if cursor['endCursor'] &&!cursor['hasNextPage']puts"end of cursor not yet reached, persist for next call: #{cursor.inspect}"File.write(cursor_file_path(demarche_number),JSON.dump(cursor.to_h), mode: 'w')elseputs'end of cursor reached, do not persist nil endCursor otherwise restart full listing'endend### that's the HTTP part# open an http connexion to our GraphQL endpointdefopen_http_connection http =Net::HTTP.new(ENDPOINT.host,ENDPOINT.port)ifENDPOINT.scheme =='https' http.use_ssl =true http.verify_mode =OpenSSL::SSL::VERIFY_NONEend httpend# the headers of our http query, include authdefrequest_headers {"Content-Type"=>"application/json","Authorization"=>"Bearer #{ENV.fetch('API_TOKEN') { raise'missing env var API_TOKEN' }}" }end# given an http connexion, request the API for pagedefrequest_page(http, last_cursor)# the data of our query data = {"query"=> query,"operationName"=>"getDemarche","variables"=> {"demarcheNumber":ENV.fetch('DEMARCHE_NUMBER') { raise'missing env var DEMARCHE_NUMBER' }.to_i,"first":100 } }# continue pagination data['variables']['after'] = last_cursor['endCursor'] if last_cursor req =Net::HTTP::Post.new(ENDPOINT, request_headers) req.body = data.to_json response = http.request(req) data =JSON.parse(response.body) dataendhttp = open_http_connection# check if we persisted a cursor so we continue pollinglast_cursor = retrieve_last_persisted_cursor(ENV['DEMARCHE_NUMBER'])data = request_page(http, last_cursor)persist_last_cursor(data,ENV['DEMARCHE_NUMBER'])dossiers = data.dig('data','demarche','dossiers','nodes')puts"Info: fetched dossiers ids: #{dossiers.map { _1['number'] }.join(', ')}"puts"Debug: #{data.inspect}"
Tant qu'il n'y aura pas de nouvelle page a proposer, votre curseur renvera les même dossiers de la dernière page. Pensez a gérer l'idempotence de votre implementation pour ce cas las.