Skip to content

Timeout on fetch while loading 841 pmtiles sources – Proposed fix by adjusting undici dispatcher #1468

@marcioecom

Description

@marcioecom

When using a configuration file (config.json) containing 841 pmtiles sources, tileserver-gl (v5.1.3) encounters a timeout error when fetching the sources. Initially, the log only displayed "fetch failed", but after adding a console.log(err) at line 768 in src/server.js, I obtained more detailed error information:

Using specified config file from config.json
Starting server
Listening at http://[::]:8080/
TypeError: fetch failed
    at Object.fetch (node:internal/deps/undici/undici:11730:11)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at runNextTicks (node:internal/process/task_queues:64:3)
    at process.processImmediate (node:internal/timers:449:9) {
  cause: ConnectTimeoutError: Connect Timeout Error
      at onConnectTimeout (node:internal/deps/undici/undici:6869:28)
      at node:internal/deps/undici/undici:6825:50
      at Immediate._onImmediate (node:internal/deps/undici/undici:6857:13)
      at process.processImmediate (node:internal/timers:478:21) {
    code: 'UND_ERR_CONNECT_TIMEOUT'
  }
}
fetch failed

Steps to Reproduce:

  1. Create a config.json file containing 841 pmtiles sources.
{
  "options": {},
  "data": {
    "sampleSource1": {
      "pmtiles": "https://example.com/tiles/sample1.pmtiles"
    },
    "sampleSource2": {
      "pmtiles": "https://example.com/tiles/sample2.pmtiles"
    }
    // ... additional sources
  }
}
  1. Start tileserver-gl using the following Docker command:
    docker run --name tileserver -v $(pwd)/config.json:/data/config.json --restart unless-stopped -p 8080:8080 -d maptiler/tileserver-gl
  2. Check the logs and observe the timeout error as described.

Environment:

  • Tileserver-gl: Version 5.1.3
  • Platform: Docker (using the maptiler/tileserver-gl image)
  • Configuration: config.json with 841 pmtiles sources (attachment available if needed)

Reference:

Proposed Solution:
I tested a solution suggested in the undici issue, which involves setting a custom global dispatcher for undici by increasing the number of connections in the pool. The code used was:

import { Agent, Pool, setGlobalDispatcher } from 'undici';

setGlobalDispatcher(
  new Agent({
    factory: (origin) => new Pool(origin, { connections: 128 }),
  }),
);

With this modification, the server is able to load all the sources (even when using a pool with just 1 connection, albeit with reduced performance). This approach can be considered either a temporary workaround or the starting point for making this configuration customizable via environment variables or configuration parameters.

Final Considerations:
I would like to discuss if this change is appropriate for the project and, if so, I can open a pull request with the implementation and necessary documentation updates. I believe this change will help handle scenarios where a large number of sources are loaded simultaneously.

Thank you for your attention, and I'm available for any further questions or adjustments.


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions