Cache category search results

And abort ongoing searches when there's a new query
This commit is contained in:
2026-03-20 19:27:26 +04:00
parent 7e98b6796c
commit 9183e3c366
3 changed files with 67 additions and 4 deletions

View File

@@ -42,7 +42,7 @@ export default class SearchRoute extends Route {
}; };
} }
pois = await this.osm.getCategoryPois(bounds, params.category); pois = await this.osm.getCategoryPois(bounds, params.category, lat, lon);
// Sort by distance from center // Sort by distance from center
pois = pois pois = pois

View File

@@ -77,10 +77,23 @@ out center;
} }
} }
async getCategoryPois(bounds, categoryId) { async getCategoryPois(bounds, categoryId, lat, lon) {
const category = getCategoryById(categoryId); const category = getCategoryById(categoryId);
if (!category || !bounds) return []; if (!category || !bounds) return [];
const queryKey = lat && lon ? `cat:${categoryId}:${lat}:${lon}` : null;
if (queryKey && this.lastQueryKey === queryKey && this.cachedResults) {
console.debug('Returning cached category results for:', queryKey);
return this.cachedResults;
}
if (this.controller) {
this.controller.abort();
}
this.controller = new AbortController();
const signal = this.controller.signal;
const { minLat, minLon, maxLat, maxLon } = bounds; const { minLat, minLon, maxLat, maxLon } = bounds;
// Build the query parts for each filter string and type // Build the query parts for each filter string and type
@@ -104,16 +117,25 @@ out center;
out center; out center;
`.trim(); `.trim();
// No caching for now as bounds change frequently
const url = `${this.settings.overpassApi}?data=${encodeURIComponent(query)}`; const url = `${this.settings.overpassApi}?data=${encodeURIComponent(query)}`;
try { try {
const res = await this.fetchWithRetry(url); const res = await this.fetchWithRetry(url, { signal });
if (!res.ok) throw new Error('Overpass request failed'); if (!res.ok) throw new Error('Overpass request failed');
const data = await res.json(); const data = await res.json();
const results = data.elements.map(this.normalizePoi); const results = data.elements.map(this.normalizePoi);
if (queryKey) {
this.lastQueryKey = queryKey;
this.cachedResults = results;
}
return results; return results;
} catch (e) { } catch (e) {
if (e.name === 'AbortError') {
console.debug('Category search aborted');
return [];
}
console.error('Category search failed', e); console.error('Category search failed', e);
return []; return [];
} }

View File

@@ -251,4 +251,45 @@ module('Unit | Service | osm', function (hooks) {
[30, 30], [30, 30],
]); ]);
}); });
test('getCategoryPois uses cache when lat/lon matches', async function (assert) {
let service = this.owner.lookup('service:osm');
// Mock settings
service.settings = { overpassApi: 'http://test-api' };
// Mock fetchWithRetry
let fetchCount = 0;
service.fetchWithRetry = async () => {
fetchCount++;
return {
ok: true,
json: async () => ({
elements: [{ id: 1, type: 'node', tags: { name: 'Test' } }],
}),
};
};
const bounds = { minLat: 0, minLon: 0, maxLat: 1, maxLon: 1 };
// First call - should fetch
await service.getCategoryPois(bounds, 'restaurants', 52.5, 13.4);
assert.strictEqual(fetchCount, 1, 'First call should trigger fetch');
// Second call with same lat/lon - should cache
await service.getCategoryPois(bounds, 'restaurants', 52.5, 13.4);
assert.strictEqual(
fetchCount,
1,
'Second call with same lat/lon should use cache'
);
// Third call with diff lat/lon - should fetch
await service.getCategoryPois(bounds, 'restaurants', 52.6, 13.5);
assert.strictEqual(
fetchCount,
2,
'Call with different lat/lon should trigger fetch'
);
});
}); });