Skip to content

Hotfix/20251222#393

Merged
SvenVw merged 6 commits into
mainfrom
hotfix/20251222
Dec 22, 2025
Merged

Hotfix/20251222#393
SvenVw merged 6 commits into
mainfrom
hotfix/20251222

Conversation

@SvenVw
Copy link
Copy Markdown
Collaborator

@SvenVw SvenVw commented Dec 22, 2025

Summary by CodeRabbit

Release Notes - Version 0.26.1

  • Bug Fixes

    • Fixed map initialization error when accessing layer data before style availability.
    • Resolved AggregateError in Elevation Atlas through optimized sampling concurrency.
  • Performance & Stability

    • Implemented server-side AHN index caching (24-hour TTL) for improved load times.
    • Added geometry simplification to reduce map rendering complexity.
    • Optimized tile processing and refined WMS layer visibility constraints at lower zoom levels.

✏️ Tip: You can customize this high-level summary in your review settings.

Closes #390, #391 and #392

…rency for sampling requests to avoid exceeding HTTP/1.1 connection limits.
…nt chunked sampling concurrency, server-side AHN index caching, geometry simplification and WMS layer zoom constraints
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Dec 22, 2025

⚠️ No Changeset found

Latest commit: c7b7d49

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

👋 Hotfix Branch PR Detected!

Before merging this Pull Request into main, please ensure you have finalized the hotfix by manually running the 'Release' workflow on this hotfix/20251222 branch.

This will:

  1. Bump package versions.
  2. Generate changelogs.
  3. Create Git tags.

You can trigger the workflow from the 'Actions' tab, selecting the 'Release' workflow, and choosing this hotfix/20251222 branch.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 22, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces performance and stability improvements to the Atlas module, including a map initialization guard fix, a new AHN index caching utility with 24-hour TTL, geometry simplification across multiple routes, and optimizations to the elevation atlas including concurrent batch sampling and WMS zoom-based visibility constraints.

Changes

Cohort / File(s) Change Summary
Bug Fix: Map Initialization Guard
fdm-app/app/components/blocks/atlas/atlas-panels.tsx
Added guard to check map.getStyle() before map.getLayer() to prevent TypeError when map style is not yet initialized
AHN Index Caching
fdm-app/app/integrations/ahn-cache.server.ts
New module-scoped cache for GeoJSON FeatureCollection with 24-hour TTL; getAhnIndex() returns cached data, fetches from PDOK on miss/expiry, validates response, logs activity, and serves stale cache on fetch failure
AHN Index Route Loader
fdm-app/app/routes/atlas.ahn-index.tsx
New route loader that calls getAhnIndex() and returns data with Cache-Control headers (public, max-age=86400, s-maxage=86400)
Elevation Atlas Optimizations
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
Removed cogUrlHillshade field; added geometry simplification; switched COG index source from remote PDOK to cached /resources/ahn-index endpoint; reduced visible tiles from 24 to 12; reworked sample gathering with concurrent chunks (batch size 4); removed hillshade overlay; updated WMS layer to render only when zoom < 13; added activeTilesLengthRef for performance tracking
Geometry Simplification Applied
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx, fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx, fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
Added geometry simplification using @turf/simplify with tolerance 0.00001 and highQuality flag in feature construction
Version & Documentation
fdm-app/package.json, fdm-app/CHANGELOG.md
Bumped version from 0.26.0 to 0.26.1; added patch notes for bug fix, stability/performance enhancements, and concurrency fix

Sequence Diagram

sequenceDiagram
    participant Client
    participant RouteLoader as Route Loader<br/>(atlas.ahn-index)
    participant Cache as AHN Cache
    participant PDOK as PDOK API

    Client->>RouteLoader: Request /resources/ahn-index
    RouteLoader->>Cache: getAhnIndex()
    
    alt Cache Hit (not expired)
        Cache-->>RouteLoader: Return cached data
    else Cache Miss or Expired
        Cache->>PDOK: Fetch AHN index GeoJSON
        PDOK-->>Cache: Response
        alt HTTP OK
            Cache->>Cache: Validate & store<br/>(24hr TTL)
            Cache-->>RouteLoader: Return data
        else HTTP Error
            Cache->>Cache: Log error
            alt Stale cache available
                Cache-->>RouteLoader: Serve stale data
            else No stale cache
                Cache-->>RouteLoader: Throw error
            end
        end
    end
    
    RouteLoader-->>Client: data() with Cache-Control headers
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Elevation route changes (farm.$b_id_farm.$calendar.atlas.elevation.tsx): Dense optimization logic with concurrent batch sampling, refactored tile visibility, and multiple property/ref updates requiring careful validation of state dependencies
  • New caching infrastructure: Review AHN cache TTL logic, error handling with stale fallback, and integration with the route loader
  • Geometry simplification across 3 routes: Verify consistent parameter usage and impact on rendering performance
  • Guard clause in atlas-panels: Ensure timing of map.getStyle() check correctly prevents the race condition
  • Dependency array updates: Confirm that effect dependencies align with new state management patterns

Possibly related PRs

Suggested reviewers

  • BoraIneviNMI
  • gerardhros

🐰 A cache blooms bright,
Tiles dance in chunks so light,
Maps guard their soul—
Smooth geometries make whole!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 3 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The PR title 'Hotfix/20251222' is generic and vague, using only a date without describing the actual changes or their purpose. Use a descriptive title that summarizes the main fix, such as 'Fix TypeError and optimize Elevation Atlas performance' or similar.
Linked Issues check ❓ Inconclusive The PR addresses issue #390 by adding a guard to check map.getStyle() before map.getLayer(), matching the stated fix exactly. However, issues #391 and #392 are referenced but not detailed. Provide details for linked issues #391 and #392 to verify all coding requirements are met, or clarify their relationship to the changeset.
Out of Scope Changes check ❓ Inconclusive The PR includes multiple changes beyond the stated issue #390: AHN caching logic, geometry simplification, WMS layer zoom constraints, and concurrent sampling. These appear to address issues #391 and #392 but lack corresponding issue details. Confirm that AHN caching, geometry simplification, and concurrency optimizations align with documented requirements in issues #391 and #392.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14350df and c7b7d49.

📒 Files selected for processing (2)
  • fdm-app/CHANGELOG.md
  • fdm-app/package.json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 22, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.47%. Comparing base (7d1083f) to head (14350df).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #393   +/-   ##
=======================================
  Coverage   87.47%   87.47%           
=======================================
  Files          91       91           
  Lines        4559     4559           
  Branches     1391     1391           
=======================================
  Hits         3988     3988           
  Misses        571      571           
Flag Coverage Δ
fdm-calculator 86.98% <ø> (ø)
fdm-core 87.66% <ø> (ø)
fdm-data 92.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot added branch:main An issue, affecting the main branch, that requires an hotfix bug Something isn't working fdm-app labels Dec 22, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
fdm-app/app/routes/atlas.ahn-index.tsx (1)

1-1: Remove unused import.

LoaderFunctionArgs is imported but not used in the loader function signature.

🔎 Suggested cleanup
-import { type LoaderFunctionArgs, data } from "react-router"
+import { data } from "react-router"
fdm-app/app/integrations/ahn-cache.server.ts (2)

13-21: Consider adding a timeout to the fetch call.

The fetch call has no timeout configured. If PDOK is slow or unresponsive, this could block the request indefinitely until the default TCP timeout (which can be several minutes).

Proposed fix using AbortSignal.timeout
         console.log("Fetching AHN index from PDOK...")
         const response = await fetch(
             "https://service.pdok.nl/rws/ahn/atom/downloads/dtm_05m/kaartbladindex.json",
+            { signal: AbortSignal.timeout(30000) } // 30 second timeout
         )

23-28: The JSON response is type-asserted without validation.

The response is cast directly to FeatureCollection without validating the structure. If PDOK returns malformed data or an error page (with a 200 status), this could cache invalid data for 24 hours.

Consider adding minimal validation before caching:

         const data = (await response.json()) as FeatureCollection
+        if (!data.features || !Array.isArray(data.features)) {
+            throw new Error("Invalid AHN index format")
+        }
         cache = {
             data,
             expires: now + CACHE_TTL,
         }
fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (3)

222-263: Double caching may cause staleness.

The client-side localStorage cache (7 days) is longer than the server-side cache (24 hours). This means clients could serve stale data even after the server cache has been refreshed.

Consider either:

  1. Reducing the client cache TTL to match or be shorter than the server cache, or
  2. Having the server endpoint return cache headers that the client respects.

The current setup isn't incorrect—it prioritizes availability over freshness—but be aware that index updates won't propagate to clients for up to 7 days.


316-324: Stale comment: update to reflect actual limit.

The comment on line 316 still mentions "24 tiles" but the actual limit is now 12.

Proposed fix
             // Find intersecting tiles
-            // Optimization: limit to e.g. 24 tiles to avoid overload
+            // Optimization: limit to 12 tiles to avoid overload
             const visibleFeatures = indexData.features

454-454: Minor: Consider if activeTiles dependency is necessary.

The updateVisibleTiles callback depends on activeTiles, but it's only used for a length check on line 283. Since you're using the updateRef pattern to ensure throttled calls use the latest callback, this works correctly, but including activeTiles in the dependency array causes the callback to be recreated on every tile update.

You could use a ref for the activeTiles length check to avoid the dependency:

+    const activeTilesLengthRef = useRef(activeTiles.length)
+    useEffect(() => {
+        activeTilesLengthRef.current = activeTiles.length
+    }, [activeTiles])

     // In updateVisibleTiles:
-    if (activeTiles.length > 0) {
+    if (activeTilesLengthRef.current > 0) {
         setActiveTiles([])
     }
     
-}, [indexData, activeTiles])
+}, [indexData])

This is a minor optimization and the current implementation is correct.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d1083f and 1274a32.

📒 Files selected for processing (10)
  • .changeset/silly-shoes-shake.md
  • .changeset/witty-foxes-lose.md
  • .changeset/yummy-wombats-live.md
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/integrations/ahn-cache.server.ts
  • fdm-app/app/routes/atlas.ahn-index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
🧰 Additional context used
🧠 Learnings (25)
📚 Learning: 2024-12-16T10:56:07.561Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 16
File: fdm-app/app/routes/app.addfarm.$b_id_farm.cultivations.$b_lu_catalogue.fertilizers.tsx:1-1
Timestamp: 2024-12-16T10:56:07.561Z
Learning: The project uses `react-router` v7, and the `data` function is exported and used for error handling in loaders and actions.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been replaced with `data()` for creating responses in loaders and actions.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: React Router v7 supports Suspense patterns by returning promises directly from loaders. The pattern is: return { data: somePromise } from loader, then use <Suspense><Await resolve={loaderData.data}>{resolvedData => ...}</Await></Suspense> in components.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-04-29T11:28:44.181Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 132
File: fdm-app/app/routes/farm.create.$b_id_farm.$calendar.access.tsx:54-68
Timestamp: 2025-04-29T11:28:44.181Z
Learning: In React Router v7, the `json()` function has been deprecated and removed. Instead, either return plain JavaScript objects directly from loaders/actions, or use the `data()` function for responses with custom status codes and headers.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-07-24T08:29:44.044Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 198
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.balance.nitrogen.$b_id.tsx:146-148
Timestamp: 2025-07-24T08:29:44.044Z
Learning: In React Router v7, the defer() function has been removed. Instead, loaders can return promises directly in the response object, and components use Suspense and Await to handle them without needing defer().

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-01-09T16:07:36.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes.ts:81-81
Timestamp: 2025-01-09T16:07:36.741Z
Learning: The route pattern "api/auth/:" in React Router is required for better-auth's handler to function correctly. The auth.handler() method in the route's loader and action functions expects this exact pattern to handle various authentication endpoints including OAuth callbacks, session management, and rate limiting.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
📚 Learning: 2025-12-15T12:19:47.858Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 376
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx:187-213
Timestamp: 2025-12-15T12:19:47.858Z
Learning: When reviewing code, prefer storing only non-sensitive UI/state data in sessionStorage. For map viewState (e.g., longitude/latitude), ensure it represents non-personal business data and that persistence across sessions is justified, documented, and respects user privacy. If persisting, use a clearly scoped, namespaced key, guard access with try/catch, and avoid syncing with servers or exposing data to third-party scripts. Apply this guideline to all TSX files that manage client-side UI state.

Applied to files:

  • fdm-app/app/routes/atlas.ahn-index.tsx
  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-31T14:29:37.599Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas.d.tsx:8-8
Timestamp: 2025-01-31T14:29:37.599Z
Learning: In the Atlas component's MapFieldsProps interface, mapStyle is intentionally restricted to "mapbox://styles/mapbox/satellite-streets-v12" as it's currently the only supported style option.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2024-11-25T14:42:26.660Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 6
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2024-11-25T14:42:26.660Z
Learning: In `fdm-app/app/components/blocks/field-map.tsx`, explicit cleanup of Mapbox GL resources is not necessary, as `react-map-gl` handles it automatically upon component unmount, and `MapRef` does not have a `remove` method.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-31T15:41:43.741Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-panels.tsx:28-28
Timestamp: 2025-01-31T15:41:43.741Z
Learning: When handling different map event types in react-map-gl v7.1.8, use MapLayerMouseEvent for mouse events (which have the point property) and ViewStateChangeEvent for view state changes. Use a type guard like 'point' in evt to safely access event-specific properties.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-01-31T16:06:33.810Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:164-212
Timestamp: 2025-01-31T16:06:33.810Z
Learning: MapGL implementations should use the shared `useMapConfig` hook for configuration and `getLayerStyle` utility for consistent styling. The hook supports both interactive and non-interactive maps, handling bounds calculation and view state management.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-06-10T13:10:03.154Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 161
File: fdm-app/app/components/blocks/field-map.tsx:0-0
Timestamp: 2025-06-10T13:10:03.154Z
Learning: When facing prop name inconsistencies with react-map-gl (like mapboxAccessToken vs mapboxApiAccessToken), using different import statements can resolve the issue more elegantly than changing prop names across multiple files.

Applied to files:

  • fdm-app/app/components/blocks/atlas/atlas-panels.tsx
📚 Learning: 2025-09-23T12:29:34.184Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm._index.tsx:160-163
Timestamp: 2025-09-23T12:29:34.184Z
Learning: In the FDM application, the fertilizer application route intentionally uses `${calendar}/field/fertilizer` instead of the originally planned `/farm/{farmId}/add/fertilizer` structure. This design decision prioritizes starting from the field list view to provide better field selection workflow before applying fertilizer, rather than direct dashboard-to-action navigation.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-09-23T12:37:58.711Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 274
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.field._index.tsx:113-148
Timestamp: 2025-09-23T12:37:58.711Z
Learning: In the FDM application, the current field data fetching implementation using Promise.all with individual API calls (getCultivations, getFertilizerApplications, getCurrentSoilData) performs acceptably even with farms containing 90+ fields. No performance issues have been observed in practice with this approach.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: A shared layout component `FarmLayoutBase` has been created in `components/custom/farm-layout-base.tsx` to maintain consistency across farm-related pages. The component handles farm selection dropdown, breadcrumb navigation, and provides a common layout structure.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: When using `updateField` from fdm-core, all 8 parameters must be provided in order: fdm, b_id, b_name, b_geometry, b_area, b_id_source, b_id_farm, and b_id_farm_source.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-09-26T08:34:50.413Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 279
File: fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx:277-283
Timestamp: 2025-09-26T08:34:50.413Z
Learning: In the fdm project, fdm-core and fdm-app are updated together as part of a monorepo structure, which eliminates legacy data concerns when new fields like b_isproductive are introduced. Both packages are synchronized, so there's no need for defensive coding against undefined values for newly introduced database fields.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-23T15:17:23.027Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-23T15:17:23.027Z
Learning: The `addField` function in fdm-core should verify field creation within the same transaction by checking the existence of the field and all its required relations (field data, acquiring info, geometry) before resolving its promise.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-08-11T12:24:32.200Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx:53-53
Timestamp: 2025-08-11T12:24:32.200Z
Learning: In `fdm-app/app/components/blocks/atlas-fields/cultivation-history.tsx`, the NMI API for cultivations guarantees that each year will be unique in the cultivation history data, so using `cultivation.year` as a React list key is safe and won't cause duplicate key warnings.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx
  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-08-13T10:33:05.313Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 0
File: :0-0
Timestamp: 2025-08-13T10:33:05.313Z
Learning: In the fdm project, fdm-calculator integration for new features like b_lu_variety is handled in separate updates from the core data model changes. When fdm-core functions are updated to support new fields, fdm-calculator can consume these enhanced APIs without requiring changes in the same PR that introduces the core functionality.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-08-11T11:55:26.053Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 233
File: fdm-app/app/integrations/nmi.ts:54-0
Timestamp: 2025-08-11T11:55:26.053Z
Learning: The NMI API Estimates endpoint (`https://api.nmi-agro.nl/estimates`) always returns the fields `b_gwl_ghg`, `b_gwl_glg`, and `cultivations` according to its specification. These fields should be kept as required (not optional) in the TypeScript return type and Zod validation schema in `fdm-app/app/integrations/nmi.ts`.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
📚 Learning: 2025-01-31T15:06:35.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 67
File: fdm-app/app/components/custom/atlas/atlas-sources.tsx:21-66
Timestamp: 2025-01-31T15:06:35.764Z
Learning: In react-map-gl components, when querying rendered features via map.queryRenderedFeatures(), the effect's dependency array must include any props that affect the map's rendered state (like source data) to ensure features are queried against the current map state.

Applied to files:

  • fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx
📚 Learning: 2025-01-09T16:03:37.764Z
Learnt from: SvenVw
Repo: SvenVw/fdm PR: 42
File: fdm-app/app/routes/farm/_b_id_farm/layout.tsx:46-95
Timestamp: 2025-01-09T16:03:37.764Z
Learning: The `FarmLayout` component in `components/custom/farm-layout.tsx` provides a reusable layout structure for farm-related pages, with support for farm selection dropdown, customizable breadcrumb titles, and flexible content rendering through either children or Outlet components.

Applied to files:

  • fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx
🧬 Code graph analysis (1)
fdm-app/app/routes/atlas.ahn-index.tsx (1)
fdm-app/app/integrations/ahn-cache.server.ts (1)
  • getAhnIndex (6-34)
🔇 Additional comments (17)
.changeset/silly-shoes-shake.md (1)

1-5: LGTM!

The changeset correctly documents the TypeError fix as a patch release with a clear description of the issue being resolved.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx (1)

2-2: LGTM!

The import of simplify from @turf/turf is appropriate for geometry simplification to improve rendering performance.

.changeset/yummy-wombats-live.md (1)

1-5: LGTM!

The changeset correctly documents the AggregateError fix with a clear explanation of the solution (chunked concurrency for HTTP/1.1 connection limits).

.changeset/witty-foxes-lose.md (1)

1-5: LGTM!

The changeset correctly documents the comprehensive optimization work, covering chunked sampling concurrency, server-side caching, geometry simplification, and WMS zoom constraints.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.fields._index.tsx (2)

2-2: LGTM!

The import of simplify from @turf/turf is appropriate for geometry simplification.


87-90: Verify the necessity of the type assertion.

The as any type assertion bypasses TypeScript's type safety. This is the same pattern observed in atlas.soil.tsx. If field.b_geometry is properly typed as a GeoJSON geometry, the assertion may be unnecessary.

Please verify whether this type assertion is required. If it's due to a type incompatibility between fdm-core's geometry type and Turf.js expectations, consider adding proper type definitions instead of using as any.

fdm-app/app/routes/farm.create.$b_id_farm.$calendar.atlas.tsx (2)

10-10: LGTM!

The import of simplify from @turf/turf is appropriate for geometry simplification.


152-155: Verify the necessity of the type assertion.

The as any type assertion is used here as well. This pattern appears across all three atlas routes that were modified. Consider addressing this systematically across all affected files.

Since this pattern appears in multiple files (soil.tsx, fields._index.tsx, and farm.create.tsx), please verify if there's a type incompatibility that can be resolved at the source (e.g., in fdm-core type definitions or by properly typing the simplify call).

fdm-app/app/components/blocks/atlas/atlas-panels.tsx (1)

42-42: Critical fix correctly implements the map style guard.

The added check !map.getStyle() ensures the map style is initialized before querying layers, preventing the TypeError described in issue #390. This guard correctly addresses the root cause where map.getLayer() internally accesses this.style, which can be undefined during initialization.

fdm-app/app/routes/atlas.ahn-index.tsx (2)

2-2: LGTM!

The import correctly references the new AHN index caching utility.


4-11: Cache headers correctly align with server-side TTL.

The 24-hour cache duration (max-age=86400, s-maxage=86400) matches the server-side cache TTL defined in ahn-cache.server.ts, ensuring consistent caching behavior across all layers. The public directive appropriately allows CDN caching for this static geospatial index data.

fdm-app/app/integrations/ahn-cache.server.ts (2)

1-4: LGTM on the cache structure and TTL configuration.

The module-scoped cache with 24-hour TTL is a reasonable choice for this use case. Note that this cache is instance-local, so in a multi-instance or serverless deployment, each instance will maintain its own cache. This is acceptable given the data is static and the TTL provides eventual consistency.


29-33: Good resilience pattern with stale cache fallback.

Serving stale cache on fetch failure is a solid approach that prevents cascading failures when PDOK is unavailable. The error is logged appropriately before falling back.

fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.elevation.tsx (4)

7-7: LGTM on the simplify import.

Using @turf/turf for geometry simplification is appropriate and aligns with changes across other atlas routes mentioned in the summary.


340-393: LGTM on chunked concurrency implementation.

The sequential chunk processing with chunkSize = 4 effectively mitigates the HTTP/1.1 connection limit issues mentioned in the PR objectives. Individual errors are caught and converted to null, allowing the aggregation to proceed with partial results.


573-591: LGTM on WMS zoom constraints.

The zoom-based rendering logic is consistent:

  • WMS layer renders when zoom < 13 with maxzoom={13} on the Source
  • COG tiles take over at zoom >= 13
  • Legend and hover behavior align with this threshold

This provides a smooth transition between overview and detailed elevation data.


134-137: Geometry simplification looks reasonable.

The tolerance of 0.00001 (degrees, equivalent to approximately 1 meter at mid-latitudes) with highQuality: true is a good balance between reducing payload size and maintaining visual fidelity for field boundaries. This setting is consistently applied across all atlas routes.

Comment thread fdm-app/app/routes/farm.$b_id_farm.$calendar.atlas.soil.tsx Outdated
@coderabbitai coderabbitai Bot added the dependencies Pull requests that update a dependency file label Dec 22, 2025
@SvenVw SvenVw merged commit a440436 into main Dec 22, 2025
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch:main An issue, affecting the main branch, that requires an hotfix bug Something isn't working dependencies Pull requests that update a dependency file fdm-app

Projects

None yet

1 participant