Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ttl to fetch promises, check metadata rows before fetching #80

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,22 @@ const levels = {
- Click on the Import button.

9. Open the browser and navigate to http://localhost:8001/mosaic-viewer to view the mosaic map.

## Environment variables

| Name | Description | Default Value |
| ----------------------- | --------------------------------------- | --------------- |
| `PGHOST` | PostgreSQL host | |
| `PGUSER` | PostgreSQL user | |
| `PGPASSWORD` | PostgreSQL password | |
| `PGDATABASE` | PostgreSQL database name | `postgres` |
| `OAM_LAYER_ID` | OpenAerialMap layer ID | `openaerialmap` |
| `PORT` | Server port | |
| `BASE_URL` | Root URL of the server | |
| `TITILER_BASE_URL` | URL of your Titiler installation | |
| `TILES_CACHE_DIR_PATH` | Path for the tiles cache | `/tiles` |
| `LOG_LEVEL` | Logging level | |
| `DB_POOL_SIZE` | Size of the PostgreSQL connection pool | `16` |
| `DB_DISABLE_SSL` | Disable SSL for PostgreSQL connection | `false` |
dqunbp marked this conversation as resolved.
Show resolved Hide resolved
| `TILE_FETCH_TIMEOUT_MS` | Tile fetch timeout in milliseconds | `60000` |
| `FETCH_QUEUE_TTL_MS` | Fetch promise queue TTL in milliseconds | `600000` |
dqunbp marked this conversation as resolved.
Show resolved Hide resolved
dqunbp marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 11 additions & 3 deletions src/mosaic.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,11 @@ async function mosaic512px(z, x, y, filters = {}) {
const metadataByUuid = {};
await Promise.all(
rows.map(async (row) => {
metadataByUuid[row.uuid] = await getGeotiffMetadata(row.uuid);
if (row?.uuid) {
metadataByUuid[row.uuid] = await getGeotiffMetadata(row.uuid);
}
})
);

const tilePromises = [];
if (z < 9) {
for (const row of rows) {
Expand Down Expand Up @@ -224,7 +225,14 @@ async function mosaic512px(z, x, y, filters = {}) {
.map((tile, index) => ({
tile,
meta: metadataByUuid[rows[index].uuid],
}));
}))
.filter(({ meta, tile }, index) => {
if (!meta) {
console.warn(`Null metadata found for tile at index ${index}, skipping...`);
return false;
}
return true;
});

// Sort tiles based on the criteria
filteredTiles.sort((a, b) => {
Expand Down
4 changes: 2 additions & 2 deletions src/mosaic_viewer.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<script>
// get zoom and center from url hash
const hash = window.location.hash.slice(1).split("/");
const [zoom = 0, lng = 0, lat = 0] = hash.filter(Boolean).map(parseFloat);
const [zoom = 0, lat = 0, lng = 0] = hash.filter(Boolean).map(parseFloat);
mapboxgl.accessToken = "";
const map = new mapboxgl.Map({
container: "map",
Expand Down Expand Up @@ -96,7 +96,7 @@
map.on("moveend", () => {
const { lng, lat } = map.getCenter();
const zoom = map.getZoom();
window.location.hash = `#${zoom.toFixed(2)}/${lng.toFixed(4)}/${lat.toFixed(4)}`;
window.location.hash = `#${zoom.toFixed(2)}/${lat.toFixed(4)}/${lng.toFixed(4)}`;
dqunbp marked this conversation as resolved.
Show resolved Hide resolved
});
</script>
</body>
Expand Down
24 changes: 22 additions & 2 deletions src/titiler_fetcher.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ const TITILER_BASE_URL = process.env.TITILER_BASE_URL;
const tileRequestQueue = new PQueue({ concurrency: numCPUs });
const activeTileRequests = new Map();

const TILE_FETCH_TIMEOUT_MS =
Number.parseInt(process.env.TILE_FETCH_TIMEOUT_MS, 10) || 1000 * 60 * 1; // 1 minute default

async function fetchTile(url) {
try {
const responsePromise = got(url, {
timeout: { request: TILE_FETCH_TIMEOUT_MS },
throwHttpErrors: true,
});

Expand All @@ -34,14 +38,30 @@ async function fetchTile(url) {
}
}

const FETCH_QUEUE_TTL_MS = Number.parseInt(process.env.FETCH_QUEUE_TTL_MS, 10) || 1000 * 60 * 10; // 10 minutes default
dqunbp marked this conversation as resolved.
Show resolved Hide resolved

async function enqueueTileFetching(tileUrl, z, x, y) {
const url = tileUrl.replace("{z}", z).replace("{x}", x).replace("{y}", y);
if (activeTileRequests.get(url)) {
return activeTileRequests.get(url);
}

const request = tileRequestQueue
.add(() => fetchTile(url), { priority: z })
.add(() => fetchTile(url), { priority: Math.pow(2, z), timeout: FETCH_QUEUE_TTL_MS })
.catch((error) => {
const logContext = {
url,
zoomLevel: z,
errorType: error.name,
errorMessage: error.message,
timeout: FETCH_QUEUE_TTL_MS
};
if (error.name === "TimeoutError") {
console.error('Tile request timeout', logContext);
} else {
console.error('Tile request failed', logContext);
}
})
.finally(() => {
activeTileRequests.delete(url);
});
Expand All @@ -62,7 +82,7 @@ async function fetchTileMetadata(uuid) {
const metadata = await got(url.href).json();
return metadata;
} catch (err) {
if (err.response && (err.response.statusCode === 404 || err.response.statusCode === 500)) {
if ([404, 500].includes(err?.response?.statusCode)) {
return null;
} else {
throw err;
Expand Down
Loading