More work on layerserver, generate

This commit is contained in:
Pieter Vander Vennet 2024-02-18 15:59:28 +01:00
parent f0823f4c4d
commit 6b507504f8
13 changed files with 124 additions and 70 deletions

9
Docs/ServerConfig/cache/Caddyfile vendored Normal file
View file

@ -0,0 +1,9 @@
cache.mapcomplete.org {
reverse_proxy /mvt {
to http://127.0.0.1:7800
}
reverse_proxy /summary {
to http://127.0.0.1:2345
}
}

15
Docs/ServerConfig/cache/cache.txt vendored Normal file
View file

@ -0,0 +1,15 @@
# Cache.mapComplete.org server config
The "cache"-server is hosted at nerdlab.
It has a full OSM-copy on disk, and has a Postgis/Postgres database with a table for every layer for quick access. It should run the tileserver and the summaryserver
## Dyndns
https://dynamicdns.park-your-domain.com/update?host=cache&domain=mapcomplete.org&password=[ddns_password]
## Setup
See SettingUpPSQL.md

View file

@ -0,0 +1,5 @@
# Hetzner
This server hosts the studio files and is used for expermintal builds.
For used hosts, see the Caddyfile

View file

@ -54,7 +54,7 @@ pg_tileserv kan hier gedownload worden: https://github.com/CrunchyData/pg_tilese
```` ````
export DATABASE_URL=postgresql://user:password@localhost:5444/osm-poi export DATABASE_URL=postgresql://user:password@localhost:5444/osm-poi
./pg_tileserv nohup ./pg_tileserv &
```` ````
Tiles are available at: Tiles are available at:
@ -64,3 +64,8 @@ map.addSource("drinking_water", {
"tiles": ["http://127.0.0.2:7800/public.drinking_water/{z}/{x}/{y}.pbf"] // http://127.0.0.2:7800/public.drinking_water.json", "tiles": ["http://127.0.0.2:7800/public.drinking_water/{z}/{x}/{y}.pbf"] // http://127.0.0.2:7800/public.drinking_water.json",
}) })
```` ````
# Rebooting:
-> Restart the docker container
->

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: Pieter Vander Vennet SPDX-FileCopyrightText: Pieter Vander Vennet
SPDX-License-Identifier: CC0 SPDX-License-Identifier: CC0-1.0

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: Pieter Vander Vennet SPDX-FileCopyrightText: Pieter Vander Vennet
SPDX-License-Identifier: CC0 SPDX-License-Identifier: CC0-1.0

View file

@ -59,4 +59,3 @@
"minzoom": 16 "minzoom": 16
} }
} }
}

View file

@ -21,7 +21,7 @@
"oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg", "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg",
"url": "https://www.openstreetmap.org" "url": "https://www.openstreetmap.org"
}, },
"mvt_layer_server": "http://127.0.0.1:7800/public.{type}_{layer}/{z}/{x}/{y}.pbf", "mvt_layer_server": "http://cache.mapcomplete.org/mvt/public.{type}_{layer}/{z}/{x}/{y}.pbf",
"disabled:oauth_credentials": { "disabled:oauth_credentials": {
"##": "DEV", "##": "DEV",
"#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/", "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/",

View file

@ -28,7 +28,7 @@ class OsmPoiDatabase {
private static readonly prefixes: ReadonlyArray<string> = ["pois", "lines", "polygons"] private static readonly prefixes: ReadonlyArray<string> = ["pois", "lines", "polygons"]
private readonly _client: Client private readonly _client: Client
private isConnected = false private isConnected = false
private supportedLayers: string[] = undefined private supportedLayers: Set<string> = undefined
private metaCache: PoiDatabaseMeta = undefined private metaCache: PoiDatabaseMeta = undefined
private metaCacheDate: Date = undefined private metaCacheDate: Date = undefined
@ -64,7 +64,7 @@ class OsmPoiDatabase {
this._client.end() this._client.end()
} }
async getLayers(): Promise<string[]> { async getLayers(): Promise<Set<string>> {
if (this.supportedLayers !== undefined) { if (this.supportedLayers !== undefined) {
return this.supportedLayers return this.supportedLayers
} }
@ -74,8 +74,8 @@ class OsmPoiDatabase {
"WHERE table_schema = 'public' AND table_name LIKE 'lines_%';" "WHERE table_schema = 'public' AND table_name LIKE 'lines_%';"
) )
const layers = result.rows.map((r) => r.table_name.substring("lines_".length)) const layers = result.rows.map((r) => r.table_name.substring("lines_".length))
this.supportedLayers = layers this.supportedLayers = new Set(layers)
return layers return this.supportedLayers
} }
async getMeta(): Promise<PoiDatabaseMeta> { async getMeta(): Promise<PoiDatabaseMeta> {
@ -218,7 +218,12 @@ const server = new Server(2345, [
let sum = 0 let sum = 0
let properties: Record<string, number> = {} let properties: Record<string, number> = {}
const availableLayers = await tcs.getLayers()
for (const layer of layers.split("+")) { for (const layer of layers.split("+")) {
console.log("Getting layer", layer)
if (!availableLayers.has(layer)) {
continue
}
const count = await tcs.getCount( const count = await tcs.getCount(
layer, layer,
Tiles.tile_bounds_lon_lat(Number(z), Number(x), Number(y)) Tiles.tile_bounds_lon_lat(Number(z), Number(x), Number(y))

View file

@ -11,9 +11,7 @@ import DynamicGeoJsonTileSource from "../TiledFeatureSource/DynamicGeoJsonTileSo
import { BBox } from "../../BBox" import { BBox } from "../../BBox"
import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeatureSource" import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeatureSource"
import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource" import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"
import { Features } from "@rgossiaux/svelte-headlessui/types"
import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource" import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource"
import { layouts } from "chart.js"
/** /**
* This source will fetch the needed data from various sources for the given layout. * This source will fetch the needed data from various sources for the given layout.
@ -21,17 +19,18 @@ import { layouts } from "chart.js"
* Note that special layers (with `source=null` will be ignored) * Note that special layers (with `source=null` will be ignored)
*/ */
export default class LayoutSource extends FeatureSourceMerger { export default class LayoutSource extends FeatureSourceMerger {
private readonly _isLoading: UIEventSource<boolean> = new UIEventSource<boolean>(false)
/** /**
* Indicates if a data source is loading something * Indicates if a data source is loading something
*/ */
public readonly isLoading: Store<boolean> = this._isLoading public readonly isLoading: Store<boolean>
constructor( constructor(
layers: LayerConfig[], layers: LayerConfig[],
featureSwitches: FeatureSwitchState, featureSwitches: FeatureSwitchState,
mapProperties: { bounds: Store<BBox>; zoom: Store<number> }, mapProperties: { bounds: Store<BBox>; zoom: Store<number> },
backend: string, backend: string,
isDisplayed: (id: string) => Store<boolean>, isDisplayed: (id: string) => Store<boolean>,
mvtAvailableLayers: Set<string>,
fullNodeDatabaseSource?: FullNodeDatabaseSource fullNodeDatabaseSource?: FullNodeDatabaseSource
) { ) {
const { bounds, zoom } = mapProperties const { bounds, zoom } = mapProperties
@ -47,18 +46,25 @@ export default class LayoutSource extends FeatureSourceMerger {
maxAge: l.maxAgeOfCache, maxAge: l.maxAgeOfCache,
}) })
) )
console.log(mapProperties) const mvtSources: FeatureSource[] = osmLayers
const mvtSources: FeatureSource[] = osmLayers.map(l => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id))) .filter((f) => mvtAvailableLayers.has(f.id))
.map((l) => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id)))
const nonMvtSources = []
const nonMvtLayers = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id))
const isLoading = new UIEventSource(false)
/* if (nonMvtLayers.length > 0) {
console.log(
"Layers ",
nonMvtLayers.map((l) => l.id),
" cannot be fetched from the cache server, defaulting to overpass/OSM-api"
)
const overpassSource = LayoutSource.setupOverpass( const overpassSource = LayoutSource.setupOverpass(
osmLayers, osmLayers,
bounds, bounds,
zoom, zoom,
featureSwitches featureSwitches
)//*/ )
/*
const osmApiSource = LayoutSource.setupOsmApiSource( const osmApiSource = LayoutSource.setupOsmApiSource(
osmLayers, osmLayers,
bounds, bounds,
@ -66,28 +72,34 @@ export default class LayoutSource extends FeatureSourceMerger {
backend, backend,
featureSwitches, featureSwitches,
fullNodeDatabaseSource fullNodeDatabaseSource
)*/ )
nonMvtSources.push(overpassSource, osmApiSource)
function setIsLoading() {
const loading = overpassSource?.runningQuery?.data || osmApiSource?.isRunning?.data
isLoading.setData(loading)
}
overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading())
osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading())
}
const geojsonSources: FeatureSource[] = geojsonlayers.map((l) => const geojsonSources: FeatureSource[] = geojsonlayers.map((l) =>
LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id)) LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
) )
super(...geojsonSources, ...fromCache, ...mvtSources, ...nonMvtSources)
super(...geojsonSources, ...fromCache, ...mvtSources) this.isLoading = isLoading
const self = this
function setIsLoading() {
// const loading = overpassSource?.runningQuery?.data || osmApiSource?.isRunning?.data
// self._isLoading.setData(loading)
} }
// overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading()) private static setupMvtSource(
// osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading()) layer: LayerConfig,
} mapProperties: { zoom: Store<number>; bounds: Store<BBox> },
isActive?: Store<boolean>
private static setupMvtSource(layer: LayerConfig, mapProperties: { zoom: Store<number>; bounds: Store<BBox> }, isActive?: Store<boolean>): FeatureSource{ ): FeatureSource {
return new DynamicMvtileSource(layer, mapProperties, { isActive }) return new DynamicMvtileSource(layer, mapProperties, { isActive })
} }
private static setupGeojsonSource( private static setupGeojsonSource(
layer: LayerConfig, layer: LayerConfig,
mapProperties: { zoom: Store<number>; bounds: Store<BBox> }, mapProperties: { zoom: Store<number>; bounds: Store<BBox> },

View file

@ -7,6 +7,7 @@ import Combine from "./UI/Base/Combine"
import { SubtleButton } from "./UI/Base/SubtleButton" import { SubtleButton } from "./UI/Base/SubtleButton"
import { Utils } from "./Utils" import { Utils } from "./Utils"
import Download from "./assets/svg/Download.svelte" import Download from "./assets/svg/Download.svelte"
import Constants from "./Models/Constants"
function webgl_support() { function webgl_support() {
try { try {
@ -19,29 +20,32 @@ function webgl_support() {
return false return false
} }
} }
async function availableLayers(): Promise<Set<string>> {
const status = await Utils.downloadJson(Constants.VectorTileServer + "/status.json")
return new Set<string>(status.layers)
}
async function main() {
// @ts-ignore // @ts-ignore
try { try {
if (!webgl_support()) { if (!webgl_support()) {
throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this." throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this."
} }
DetermineLayout.GetLayout() const [layout, availableLayers] = await Promise.all([
.then((layout) => { DetermineLayout.GetLayout(),
await availableLayers(),
])
const state = new ThemeViewState(layout) const state = new ThemeViewState(layout)
const main = new SvelteUIElement(ThemeViewGUI, { state }) const main = new SvelteUIElement(ThemeViewGUI, { state })
main.AttachTo("maindiv") main.AttachTo("maindiv")
}) } catch (err) {
.catch((err) => {
console.error("Error while initializing: ", err, err.stack) console.error("Error while initializing: ", err, err.stack)
const customDefinition = DetermineLayout.getCustomDefinition() const customDefinition = DetermineLayout.getCustomDefinition()
new Combine([ new Combine([
new FixedUiElement(err).SetClass("block alert"), new FixedUiElement(err).SetClass("block alert"),
customDefinition?.length > 0 customDefinition?.length > 0
? new SubtleButton( ? new SubtleButton(new SvelteUIElement(Download), "Download the raw file").onClick(
new SvelteUIElement(Download), () =>
"Download the raw file"
).onClick(() =>
Utils.offerContentsAsDownloadableFile( Utils.offerContentsAsDownloadableFile(
DetermineLayout.getCustomDefinition(), DetermineLayout.getCustomDefinition(),
"mapcomplete-theme.json", "mapcomplete-theme.json",
@ -50,7 +54,7 @@ try {
) )
: undefined, : undefined,
]).AttachTo("maindiv") ]).AttachTo("maindiv")
})
} catch (err) {
new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv")
} }
}
main().then((_) => {})