Files
map-asset-gateway/demo/demo_geojson_flow.ps1
T
Harmon 73ad03fa59 Rewrite the gateway around health, retries, slicing and a Windows service
Scanner
- manifest lookup is now depth-bounded and prunes numeric zoom directories, so
  a scan no longer walks the whole tile payload
- rescans only report a version as updated when something actually changed
- overlapping runs are refused instead of interleaving their bookkeeping

Hot path
- token authorisation loads only that token grants and throttles the
  last_used_at write instead of touching it on every tile
- SQLite runs in WAL with a busy timeout and a real connection pool
- the catalog lookup used by /tiles no longer loads every basemap

Security
- the admin surface requires ADMIN_TOKEN (bearer) or ADMIN_USER/ADMIN_PASSWORD
  (basic), and the service refuses to bind off-host without credentials
- CORS is an explicit allow-list; newly minted tokens never reach a redirect URL
- client tokens are redacted from the access log

Operations
- resource health inspection flags a moved or deleted tile root before a 404
- pushes retry with backoff and can be re-queued by hand; the schedule lives in
  the database so a restart does not lose it
- access log plus /metrics counters

Image slicing
- tile_jobs drive the GDAL bundled with QGIS via scripts/gdal2tiles-qgis.bat
- layer_sources remembers what a layer is made of: submit one source to append
  a flight, or all of them to rebuild the layer as a VRT mosaic with no tile
  seams; the console exposes both, including a one-click rebuild
- slicing is available to integrations through a narrow slice token scope
  (submit, poll, idempotent by code, completion callback)

Console
- rebuilt around a fixed rail and single-view navigation with health and
  outstanding work leading, instead of one long scrolling page

Windows service
- native install/start/stop/status with crash recovery, auto-start and a
  rotating log file, so no NSSM wrapper is needed
- start-all.bat and stop-all.bat are removed: they killed the process by port
  with taskkill, which fought the service restart policy

Verified with 49 tests and live runs against real tile data and real GDAL.
2026-10-16 10:35:30 +08:00

136 lines
4.3 KiB
PowerShell

param(
[string]$ProjectCode = "default",
[string]$ResourceCode = ("demo_geojson_" + (Get-Date -Format "yyyyMMdd_HHmmss")),
[string]$InputPath = "",
[string]$RequestedBy = "demo-user",
[switch]$Push,
[string]$TargetSystemCode = "",
[string]$CallbackUrl = "",
[bool]$WaitForJob = $true,
[switch]$StartStack,
[switch]$StartCallbackReceiver,
[switch]$KeepProcesses,
[int]$ApiPort = 28910,
[int]$TilePort = 28900,
[int]$CallbackPort = 28920
)
. (Join-Path $PSScriptRoot "common.ps1")
$stack = $null
$callback = $null
$run = New-RsRunContext -Prefix "geojson_flow"
try {
Import-RsDemoEnvironment
if ($StartStack) {
$stack = Start-RsDemoStack -ApiPort $ApiPort -TilePort $TilePort -IncludeWorker -RunID $run.RunID
}
if ($StartCallbackReceiver) {
$callback = Start-RsCallbackReceiver -Port $CallbackPort -RunID ($run.RunID + "_callback")
$Push = $true
$CallbackUrl = $callback.CallbackURL
}
if (-not $InputPath) {
$geojsonDir = Join-Path (Get-RsRepoRoot) "data\geojson\demo"
New-Item -ItemType Directory -Force -Path $geojsonDir | Out-Null
$InputPath = Join-Path $geojsonDir ($ResourceCode + ".geojson")
@"
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"code": "$ResourceCode",
"kind": "demo"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[110.0, 20.0],
[112.0, 20.0],
[112.0, 22.0],
[110.0, 22.0],
[110.0, 20.0]
]
]
}
}
]
}
"@ | Set-Content -LiteralPath $InputPath -Encoding UTF8
}
$publicUrl = "/geojson/demo/" + [System.IO.Path]::GetFileName($InputPath)
$project = Encode-RsURIComponent $ProjectCode
$resource = Invoke-RsApi -Method "POST" -Path "/api/v1/projects/$project/geojson-resources" -Body @{
code = $ResourceCode
name = $ResourceCode
description = "Registered by demo_geojson_flow.ps1"
storage_uri = ConvertTo-RsFileUri $InputPath
public_url = $publicUrl
metadata = @{
demo_run = $run.RunID
}
}
$pushResponse = $null
$job = $null
if ($Push -or $TargetSystemCode -or $CallbackUrl) {
$body = @{
resource_kind = "geojson_resource"
geojson_resource_id = $resource.id
requested_by = $RequestedBy
}
if ($TargetSystemCode) {
$body.target_system_code = $TargetSystemCode
}
if ($CallbackUrl) {
$body.callback_url = $CallbackUrl
}
if (-not $TargetSystemCode -and -not $CallbackUrl) {
$body.callback_url = "http://127.0.0.1:8920/callback"
}
$pushResponse = Invoke-RsApi -Method "POST" -Path "/api/v1/projects/$project/delivery-pushes" -Body $body
if ($WaitForJob) {
$job = Wait-RsJob -JobID $pushResponse.job.id
}
}
$callbackRecord = $null
if ($callback) {
Start-Sleep -Seconds 1
$callbackRecord = Get-RsLatestCallbackRecord -OutputDirectory $callback.OutputDirectory
}
[ordered]@{
run_id = $run.RunID
api_base_url = Get-RsApiBaseUrl
tile_base_url = Get-RsTileBaseUrl
resource_id = $resource.id
resource_code = $resource.code
input_path = [System.IO.Path]::GetFullPath($InputPath)
public_url = $resource.public_url
download_url = $resource.download_url
push_job_id = if ($pushResponse) { $pushResponse.job.id } else { $null }
push_job_status = if ($job) { $job.status } elseif ($pushResponse) { $pushResponse.job.status } else { $null }
callback_url = if ($pushResponse) { $pushResponse.callback_url } else { $CallbackUrl }
callback_record_path = if ($callbackRecord) { $callbackRecord.Path } else { $null }
} | ConvertTo-Json -Depth 12
}
finally {
if (-not $KeepProcesses) {
if ($callback) {
Stop-RsBackgroundProcesses -Processes @($callback.Process)
}
if ($stack) {
Stop-RsBackgroundProcesses -Processes $stack.Processes
}
}
}