feat: add governed nationwide AOI orchestration and CUDA enforcement
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-26 05:23:33 +02:00
parent 25b6f1ab39
commit 2be72fac58
50 changed files with 1596 additions and 51 deletions
@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from 'react'
import { formatError } from '../lib/formatError'
import { datasetsApi } from '../services/api/datasets'
import { aoiOperationsApi } from '../services/api/aoiOperations'
import type { DatasetCreateResponse, VectorSelectionBBox, VectorSelectionResponse } from '../types'
import { terrainSelectionToMapSelection } from '../lib/terrainSelection'
import { floodHazardSelectionToMapSelection } from '../lib/floodHazardSelection'
@@ -22,6 +23,8 @@ export interface MapThemeAcquisition {
productKey: string
displayName: string
historyProductKeys?: string[]
coverageZone?: string
serverOrchestrated?: boolean
}
export interface MapThemeQuery<TThemeId extends string> {
@@ -116,6 +119,30 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
const resultLimit = featureLimit ?? 1000
if (acquisition) {
const requestedBboxes = acquisitionBboxes?.length ? acquisitionBboxes : [bbox]
if (acquisition.serverOrchestrated) {
let operation = await aoiOperationsApi.create(selectedProjectId, {
...(areaId ? { area_id: areaId } : { bbox }),
operation_type: 'acquire',
provider_key: acquisition.kind,
product_key: acquisition.productKey,
coverage_zone: acquisition.coverageZone,
max_attempts: 3,
parameters_json: { force_refresh: false },
})
const deadline = Date.now() + 20 * 60 * 1000
while (['queued', 'running'].includes(operation.status) && Date.now() < deadline) {
await new Promise((resolve) => window.setTimeout(resolve, 1500))
operation = await aoiOperationsApi.get(selectedProjectId, operation.id)
}
if (operation.status !== 'success') {
throw new Error(operation.error_message || `De gebiedsverwerking eindigde als ${operation.status}.`)
}
const outputIds = Array.isArray(operation.result_json?.['output_dataset_ids'])
? operation.result_json['output_dataset_ids'].map(String)
: []
acquiredDatasets = await Promise.all(outputIds.map((datasetId) => datasetsApi.get(selectedProjectId, datasetId)))
dataset = acquiredDatasets[0]
}
const acquireProduct = async (acquisitionBbox: VectorSelectionBBox, productKey: string) => {
const commonPayload = {
bbox: acquisitionBbox,
@@ -166,7 +193,7 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
}
return datasetsApi.get(selectedProjectId, acquisitionJob.output_dataset_id)
}
const acquisitionResults = await settleWithConcurrency(
const acquisitionResults = acquisition.serverOrchestrated ? [] : await settleWithConcurrency(
requestedBboxes,
1,
(acquisitionBbox) => acquireProduct(acquisitionBbox, acquisition.productKey),
@@ -175,7 +202,7 @@ export function useMapThemeSelectionInsights<TThemeId extends string>(
if (failedAcquisition?.status === 'rejected') {
throw failedAcquisition.reason
}
acquiredDatasets = acquisitionResults.flatMap((item) => item.status === 'fulfilled' ? [item.value] : [])
if (!acquisition.serverOrchestrated) acquiredDatasets = acquisitionResults.flatMap((item) => item.status === 'fulfilled' ? [item.value] : [])
dataset = acquiredDatasets[0]
const historyProductKeys = acquisition.kind === 'walous'
? [...new Set(acquisition.historyProductKeys ?? [])].filter((key) => key !== acquisition.productKey)