perf(create-spot): cap reverse-geocode at 2.5s so publish can't stall before signing
This commit is contained in:
parent
f791e5375c
commit
c08592144a
2 changed files with 21 additions and 6 deletions
10
AGENTS.md
10
AGENTS.md
|
|
@ -1120,9 +1120,13 @@ session with **no other memory of this project**. So:
|
||||||
the form autosaves via **`useFormDraft`** (generalized from `useLabDraft`, same
|
the form autosaves via **`useFormDraft`** (generalized from `useLabDraft`, same
|
||||||
resume-banner pattern). ⚠️ Leaflet's base CSS is **CDN-loaded in `index.html`**
|
resume-banner pattern). ⚠️ Leaflet's base CSS is **CDN-loaded in `index.html`**
|
||||||
(`src/main.tsx` just has a comment) — a new Leaflet map needs no CSS import.
|
(`src/main.tsx` just has a comment) — a new Leaflet map needs no CSS import.
|
||||||
Still open: the 60 m duplicate check still runs on submit with
|
Follow-ups in the same pass: the 60 m duplicate check now runs **at pin-time**
|
||||||
`useSkateSpots(500)` (move it to pin-time + a targeted geohash query), and
|
(debounced, warning under the map) using the **same `useSkateSpots(2000)` cache
|
||||||
publish still blocks on `reverseGeocodeRegions` before signing.
|
key as the map** (was a second `useSkateSpots(500)` query); and publish **caps
|
||||||
|
the reverse-geocode at `GEOCODE_BUDGET_MS` (2.5 s)** so a slow provider can't
|
||||||
|
stall signing (a miss falls back to the stats' read-time region derivation).
|
||||||
|
⚠️ A geohash-prefix nearby query is still impossible — relays only exact-match
|
||||||
|
`#g` — so the 2000-spot cache remains the mechanism.
|
||||||
- **Map pin rendering (perf, 2026-09-29):** the spot/tour/event/crew marker
|
- **Map pin rendering (perf, 2026-09-29):** the spot/tour/event/crew marker
|
||||||
effect in `SpotMap.tsx` used to `clearLayers()` + rebuild **every** marker
|
effect in `SpotMap.tsx` used to `clearLayers()` + rebuild **every** marker
|
||||||
whenever the parent handed it fresh arrays, and added each marker with a
|
whenever the parent handed it fresh arrays, and added each marker with a
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import { PhotoDropzone } from '@/components/PhotoDropzone';
|
||||||
import { TagInput } from '@/components/TagInput';
|
import { TagInput } from '@/components/TagInput';
|
||||||
import { SpotLocationPicker, type LatLng } from '@/components/SpotLocationPicker';
|
import { SpotLocationPicker, type LatLng } from '@/components/SpotLocationPicker';
|
||||||
import { SKATE_SPOT_KIND } from '@/lib/types';
|
import { SKATE_SPOT_KIND } from '@/lib/types';
|
||||||
import { reverseGeocodeRegions, pushRegionTags } from '@/lib/geocodeRegions';
|
import { reverseGeocodeRegions, pushRegionTags, type GeocodedRegions } from '@/lib/geocodeRegions';
|
||||||
import { spotCategories, MAX_TAGS, shelterOptions, DEFAULT_SHELTER, SHELTERED_VALUES, type ShelterType } from '@/lib/skateTags';
|
import { spotCategories, MAX_TAGS, shelterOptions, DEFAULT_SHELTER, SHELTERED_VALUES, type ShelterType } from '@/lib/skateTags';
|
||||||
import { SPOT_TAG_CATEGORY_KEYS, SPOT_TAG_CATEGORY_DESC_KEYS, SHELTER_KEYS, SHELTER_DESC_KEYS } from '@/lib/labelKeys';
|
import { SPOT_TAG_CATEGORY_KEYS, SPOT_TAG_CATEGORY_DESC_KEYS, SHELTER_KEYS, SHELTER_DESC_KEYS } from '@/lib/labelKeys';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
@ -68,6 +68,9 @@ type SpotDraft = {
|
||||||
|
|
||||||
const DRAFT_PREFIX = 'skatespots:spot-draft:';
|
const DRAFT_PREFIX = 'skatespots:spot-draft:';
|
||||||
|
|
||||||
|
/** How long to wait for a reverse-geocode before publishing without region tags. */
|
||||||
|
const GEOCODE_BUDGET_MS = 2500;
|
||||||
|
|
||||||
export default function CreateSpotPage() {
|
export default function CreateSpotPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|
@ -386,8 +389,16 @@ export default function CreateSpotPage() {
|
||||||
|
|
||||||
// Reverse geocode to get structured city/country tags (best-effort; the
|
// Reverse geocode to get structured city/country tags (best-effort; the
|
||||||
// helper never throws). These power Sasquatch's city/country search and
|
// helper never throws). These power Sasquatch's city/country search and
|
||||||
// the /stats region breakdown.
|
// the /stats region breakdown. Capped so a slow provider can't make
|
||||||
const geo = await reverseGeocodeRegions(lat, lng);
|
// "Publish" feel stuck — a miss is covered by the stats' read-time
|
||||||
|
// derivation of an untagged pin's coords.
|
||||||
|
const emptyRegions: GeocodedRegions = { city: '', country: '', state: '', countryCode: '' };
|
||||||
|
const geo = await Promise.race([
|
||||||
|
reverseGeocodeRegions(lat, lng),
|
||||||
|
new Promise<GeocodedRegions>((resolve) => {
|
||||||
|
window.setTimeout(() => resolve(emptyRegions), GEOCODE_BUDGET_MS);
|
||||||
|
}),
|
||||||
|
]);
|
||||||
let locationStr = location.trim();
|
let locationStr = location.trim();
|
||||||
if (!locationStr && geo.city) {
|
if (!locationStr && geo.city) {
|
||||||
// Auto-populate an empty address from the geocode.
|
// Auto-populate an empty address from the geocode.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue