Paginazione e intervalli di tempo

Come percorrere le consegne e i record delle collezioni con un cursore opaco, e perché le une richiedono un intervallo di tempo e gli altri no.

Due endpoint paginano, e lo fanno in modo diverso di proposito:

ElencoIntervalloOrdineIl cursore è legato a
Consegnefrom e to, obbligatori, al massimo 366 giorniDal più recenteL'intervallo che ha richiesto
Record delle collezioninessuno — si percorre l'intera collezioneDalla modifica più vecchiaRistorante, collezione e limit

Entrambi rispondono { "data": [...], "nextCursor": string | null }, entrambi limitano limit a 100 con un valore predefinito di 50, ed entrambi vogliono che il cursore venga rimandato indietro intatto. Il resto di questa pagina riguarda l'elenco delle consegne; l'altro è trattato nella pagina sulle collezioni.

Le consegne sono immutabili e interessanti per data, quindi accettano un intervallo. I record delle collezioni cambiano sul posto, quindi un intervallo su di essi sarebbe una bugia — si percorre la collezione e si riconcilia.

L'elenco delle consegne

Richiede un intervallo di tempo esplicito e obbligatorio e restituisce una pagina più un cursore opaco.

GET /v1/restaurants/{restaurantId}/deliveries
  ?from=1787846400000
  &to=1788451200000
  &limit=50
  &cursor=eyJpZCI6…
ParametroObbligatorioRegole
fromMillisecondi dall'epoch, come stringa di cifre. Incluso.
toMillisecondi dall'epoch, come stringa di cifre. Incluso.
limitnoDa 1 a 100. Il valore predefinito è 50.
cursornoIl nextCursor della pagina precedente, invariato.

to deve essere maggiore o uguale a from, e l'ampiezza deve essere al massimo di 366 giorni. Qualsiasi altra cosa risponde 400. L'intervallo è obbligatorio anziché predefinito perché è con un valore predefinito che un'integrazione comincia in silenzio a rileggere un decennio di record ogni notte.

Ordinamento

Dal più recente: in ordine decrescente per occurredAt, poi decrescente per id per sciogliere i pari merito. Due consegne registrate nello stesso millisecondo hanno quindi un ordine stabile e ripetibile, che è ciò che rende solido il cursore.

Percorrere le pagine

nextCursor è null sull'ultima pagina e una stringa altrimenti. Lo rimandi indietro intatto — è una posizione codificata in base64url, non un documento da analizzare, e la sua struttura interna cambierà senza preavviso.

async function* deliveries({ apiKey, restaurantId, from, to }) {
  const base = `https://api.backresto.com/v1/restaurants/${restaurantId}/deliveries`;
  let cursor = null;

  do {
    const url = new URL(base);
    url.searchParams.set('from', from);
    url.searchParams.set('to', to);
    url.searchParams.set('limit', '100');
    if (cursor !== null) {
      url.searchParams.set('cursor', cursor);
    }

    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${apiKey}` }
    });
    if (!response.ok) {
      throw new Error(`BackResto ${response.status}`);
    }

    const page = await response.json();
    yield* page.data;
    cursor = page.nextCursor;
  } while (cursor !== null);
}

Mantenga from e to identici per ogni pagina di un percorso. Il cursore codifica una posizione all'interno dell'intervallo che ha richiesto; cambiare l'intervallo a metà percorso non è una richiesta supportata e non le darà quello che si aspetta.

Interrogazione incrementale

Le consegne sono immutabili una volta registrate, quindi un'interrogazione incrementale è semplice: conservi l'occurredAt del record più recente che ha memorizzato e lo usi come from successivo.

Due dettagli che vale la pena implementare:

  • Si sovrapponga di proposito. Faccia iniziare la finestra successiva un po' prima dell'ultimo record che ha visto — un'ora è più che sufficiente — e deduplichi su id. Un dispositivo che era offline durante il servizio carica i dati quando si riconnette, quindi una consegna può diventare visibile dopo un'interrogazione che copriva già il suo timestamp.
  • Non superi mai i 366 giorni. Se il suo job non gira da molto tempo, percorra il divario in finestre di un anno anziché chiederlo tutto in una volta.

Una pagina vuota non è la prova che non sia successo nulla — veda la nota sulla completezza.

Ultimo aggiornamento 2026-09-19.