mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 06:46:42 +02:00
chore(geocoding): remove Pelias + close 3 bypass paths to public Nominatim
Pelias was retired from the Mac mini on 2026-04-28; photon-self (self-hosted Photon on mana-gpu) has been the live primary since then. This removes the now-dead Pelias adapter, config, tests, and the services/mana-geocoding/pelias/ stack — the entire compose file, the geojsonify_place_details.js patch, the setup.sh import script. Provider chain is now `photon-self → photon → nominatim`. The chain keeps its `privacy: 'local' | 'public'` split, sensitive-query blocking, coord quantization, and aggressive caching unchanged. Three direct calls to nominatim.openstreetmap.org that bypassed mana-geocoding now route through the wrapper: - citycorners/add-city + citycorners/cities/[slug]/add use the shared searchAddress() client (browser → same-origin proxy → mana-geocoding → photon-self). - memoro mobile drops its OSM reverse-geocoding fallback entirely; Expo's on-device reverse-geocoding stays as the sole path. Routing through the wrapper would require a memoro-server proxy endpoint — a follow-up if Expo's quality proves insufficient. Other behavioral changes: - CACHE_PUBLIC_TTL_MS dropped from 7d → 1h. The long TTL was a privacy-amplification trick from the Pelias era; with photon-self serving the bulk of traffic, a transient cross-LAN blip was pinning cached fallback answers for days. 1h gives quick recovery. - /health/pelias renamed to /health/photon-self; prometheus blackbox config + status-page generator updated. - mana-geocoding container no longer needs `extra_hosts: host.docker.internal:host-gateway` (was only there for the Pelias-on-host-network era). 113 tests passing. CLAUDE.md rewritten to reflect the post-Pelias architecture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7bca16dfa7
commit
2bbcf14aba
35 changed files with 330 additions and 1262 deletions
|
|
@ -21,10 +21,10 @@ interface CachedAnswer {
|
|||
}
|
||||
|
||||
/**
|
||||
* TTL chooser. Public-API results (Photon/Nominatim) get the longer TTL —
|
||||
* caching aggressively is the main privacy lever once the query has
|
||||
* already left our network. Local results stay on the shorter TTL because
|
||||
* the Pelias index can be re-imported; we don't want stale local data.
|
||||
* TTL chooser. Public-API results (photon/nominatim) get a shorter TTL
|
||||
* (1h) so a transient blip in photon-self doesn't pin stale fallback
|
||||
* answers in the cache for days. Local results (photon-self) get the
|
||||
* longer 24h TTL.
|
||||
*
|
||||
* Sensitive-query notices are cached on the short TTL too (the user might
|
||||
* retry from a different angle quickly), and `undefined` provider (chain
|
||||
|
|
|
|||
|
|
@ -9,35 +9,43 @@ export function createHealthRoutes(config: Config, chain: ProviderChain) {
|
|||
app.get('/', (c) => c.json({ status: 'ok', service: 'mana-geocoding' }));
|
||||
|
||||
/**
|
||||
* Upstream Pelias health. Proxies a request to the Pelias API so
|
||||
* monitoring can reach it without `extra_hosts: host.docker.internal`
|
||||
* on the blackbox exporter.
|
||||
* Upstream photon-self health. Proxies a request to the self-hosted
|
||||
* Photon so monitoring can reach it without `extra_hosts:
|
||||
* host.docker.internal` on the blackbox exporter.
|
||||
*
|
||||
* Backwards-compatible: existing prometheus probes against this
|
||||
* endpoint keep working. Now reports `degraded` (200) instead of `down`
|
||||
* (503) when Pelias is unreachable but a fallback provider is healthy
|
||||
* — the system can still serve queries, just slower / less precise.
|
||||
* Reports `degraded` (200) instead of `down` (503) when photon-self is
|
||||
* unreachable but a public fallback (photon / nominatim) is healthy —
|
||||
* the system can still serve queries, just at the cost of leaking the
|
||||
* query content to a third party.
|
||||
*/
|
||||
app.get('/pelias', async (c) => {
|
||||
app.get('/photon-self', async (c) => {
|
||||
const upstream = config.photonSelf.apiUrl;
|
||||
if (!upstream) {
|
||||
return c.json({ status: 'unconfigured', error: 'PHOTON_SELF_API_URL is unset' }, 503);
|
||||
}
|
||||
try {
|
||||
const res = await fetch(`${config.pelias.apiUrl}/status`, {
|
||||
const res = await fetch(`${upstream}/api?q=Konstanz&limit=1`, {
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
if (!res.ok && res.status !== 404) {
|
||||
if (!res.ok) {
|
||||
return c.json(
|
||||
{ status: 'degraded', upstream: res.status, fallbackAvailable: chainHasFallback(chain) },
|
||||
chainHasFallback(chain) ? 200 : 503
|
||||
{
|
||||
status: 'degraded',
|
||||
upstream: res.status,
|
||||
fallbackAvailable: chainHasPublicFallback(chain),
|
||||
},
|
||||
chainHasPublicFallback(chain) ? 200 : 503
|
||||
);
|
||||
}
|
||||
return c.json({ status: 'ok', upstream: 'pelias-api' });
|
||||
return c.json({ status: 'ok', upstream: 'photon-self' });
|
||||
} catch (e) {
|
||||
return c.json(
|
||||
{
|
||||
status: chainHasFallback(chain) ? 'degraded' : 'down',
|
||||
status: chainHasPublicFallback(chain) ? 'degraded' : 'down',
|
||||
error: e instanceof Error ? e.message : 'unknown',
|
||||
fallbackAvailable: chainHasFallback(chain),
|
||||
fallbackAvailable: chainHasPublicFallback(chain),
|
||||
},
|
||||
chainHasFallback(chain) ? 200 : 503
|
||||
chainHasPublicFallback(chain) ? 200 : 503
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -56,10 +64,10 @@ export function createHealthRoutes(config: Config, chain: ProviderChain) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if any non-Pelias provider is currently believed healthy. Used
|
||||
* to soften /pelias health to "degraded" instead of "down" when a
|
||||
* fallback can still serve traffic.
|
||||
* Check if any public fallback provider is currently believed healthy.
|
||||
* Used to soften /photon-self health to "degraded" instead of "down"
|
||||
* when a public fallback can still serve traffic.
|
||||
*/
|
||||
function chainHasFallback(chain: ProviderChain): boolean {
|
||||
return chain.getHealthSnapshot().some((p) => p.name !== 'pelias' && p.healthy);
|
||||
function chainHasPublicFallback(chain: ProviderChain): boolean {
|
||||
return chain.getHealthSnapshot().some((p) => p.name !== 'photon-self' && p.healthy);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue