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
./pg_tileserv
nohup ./pg_tileserv &
````
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",
})
````
# Rebooting:
-> Restart the docker container
->

View file

@ -1,2 +1,2 @@
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-License-Identifier: CC0
SPDX-License-Identifier: CC0-1.0

View file

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

View file

@ -21,7 +21,7 @@
"oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg",
"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": {
"##": "DEV",
"#": "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 readonly _client: Client
private isConnected = false
private supportedLayers: string[] = undefined
private supportedLayers: Set<string> = undefined
private metaCache: PoiDatabaseMeta = undefined
private metaCacheDate: Date = undefined
@ -64,7 +64,7 @@ class OsmPoiDatabase {
this._client.end()
}
async getLayers(): Promise<string[]> {
async getLayers(): Promise<Set<string>> {
if (this.supportedLayers !== undefined) {
return this.supportedLayers
}
@ -74,8 +74,8 @@ class OsmPoiDatabase {
"WHERE table_schema = 'public' AND table_name LIKE 'lines_%';"
)
const layers = result.rows.map((r) => r.table_name.substring("lines_".length))
this.supportedLayers = layers
return layers
this.supportedLayers = new Set(layers)
return this.supportedLayers
}
async getMeta(): Promise<PoiDatabaseMeta> {
@ -218,7 +218,12 @@ const server = new Server(2345, [
let sum = 0
let properties: Record<string, number> = {}
const availableLayers = await tcs.getLayers()
for (const layer of layers.split("+")) {
console.log("Getting layer", layer)
if (!availableLayers.has(layer)) {
continue
}
const count = await tcs.getCount(
layer,
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 LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeatureSource"
import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"
import { Features } from "@rgossiaux/svelte-headlessui/types"
import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource"
import { layouts } from "chart.js"
/**
* 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)
*/
export default class LayoutSource extends FeatureSourceMerger {
private readonly _isLoading: UIEventSource<boolean> = new UIEventSource<boolean>(false)
/**
* Indicates if a data source is loading something
*/
public readonly isLoading: Store<boolean> = this._isLoading
public readonly isLoading: Store<boolean>
constructor(
layers: LayerConfig[],
featureSwitches: FeatureSwitchState,
mapProperties: { bounds: Store<BBox>; zoom: Store<number> },
backend: string,
isDisplayed: (id: string) => Store<boolean>,
mvtAvailableLayers: Set<string>,
fullNodeDatabaseSource?: FullNodeDatabaseSource
) {
const { bounds, zoom } = mapProperties
@ -47,47 +46,60 @@ export default class LayoutSource extends FeatureSourceMerger {
maxAge: l.maxAgeOfCache,
})
)
console.log(mapProperties)
const mvtSources: FeatureSource[] = osmLayers.map(l => LayoutSource.setupMvtSource(l, mapProperties, isDisplayed(l.id)))
const mvtSources: FeatureSource[] = osmLayers
.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(
osmLayers,
bounds,
zoom,
featureSwitches
)
const osmApiSource = LayoutSource.setupOsmApiSource(
osmLayers,
bounds,
zoom,
backend,
featureSwitches,
fullNodeDatabaseSource
)
nonMvtSources.push(overpassSource, osmApiSource)
/*
const overpassSource = LayoutSource.setupOverpass(
osmLayers,
bounds,
zoom,
featureSwitches
)//*/
/*
const osmApiSource = LayoutSource.setupOsmApiSource(
osmLayers,
bounds,
zoom,
backend,
featureSwitches,
fullNodeDatabaseSource
)*/
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) =>
LayoutSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
)
super(...geojsonSources, ...fromCache, ...mvtSources, ...nonMvtSources)
super(...geojsonSources, ...fromCache, ...mvtSources)
const self = this
function setIsLoading() {
// const loading = overpassSource?.runningQuery?.data || osmApiSource?.isRunning?.data
// self._isLoading.setData(loading)
}
// overpassSource?.runningQuery?.addCallbackAndRun((_) => setIsLoading())
// osmApiSource?.isRunning?.addCallbackAndRun((_) => setIsLoading())
this.isLoading = isLoading
}
private static setupMvtSource(layer: LayerConfig, mapProperties: { zoom: Store<number>; bounds: Store<BBox> }, isActive?: Store<boolean>): FeatureSource{
private static setupMvtSource(
layer: LayerConfig,
mapProperties: { zoom: Store<number>; bounds: Store<BBox> },
isActive?: Store<boolean>
): FeatureSource {
return new DynamicMvtileSource(layer, mapProperties, { isActive })
}
private static setupGeojsonSource(
layer: LayerConfig,
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 { Utils } from "./Utils"
import Download from "./assets/svg/Download.svelte"
import Constants from "./Models/Constants"
function webgl_support() {
try {
@ -19,38 +20,41 @@ function webgl_support() {
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
try {
if (!webgl_support()) {
throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this."
}
const [layout, availableLayers] = await Promise.all([
DetermineLayout.GetLayout(),
await availableLayers(),
])
const state = new ThemeViewState(layout)
const main = new SvelteUIElement(ThemeViewGUI, { state })
main.AttachTo("maindiv")
} catch (err) {
console.error("Error while initializing: ", err, err.stack)
const customDefinition = DetermineLayout.getCustomDefinition()
new Combine([
new FixedUiElement(err).SetClass("block alert"),
// @ts-ignore
try {
if (!webgl_support()) {
throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this."
}
DetermineLayout.GetLayout()
.then((layout) => {
const state = new ThemeViewState(layout)
const main = new SvelteUIElement(ThemeViewGUI, { state })
main.AttachTo("maindiv")
})
.catch((err) => {
console.error("Error while initializing: ", err, err.stack)
const customDefinition = DetermineLayout.getCustomDefinition()
new Combine([
new FixedUiElement(err).SetClass("block alert"),
customDefinition?.length > 0
? new SubtleButton(
new SvelteUIElement(Download),
"Download the raw file"
).onClick(() =>
customDefinition?.length > 0
? new SubtleButton(new SvelteUIElement(Download), "Download the raw file").onClick(
() =>
Utils.offerContentsAsDownloadableFile(
DetermineLayout.getCustomDefinition(),
"mapcomplete-theme.json",
{ mimetype: "application/json" }
)
)
: undefined,
]).AttachTo("maindiv")
})
} catch (err) {
new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv")
)
: undefined,
]).AttachTo("maindiv")
}
}
main().then((_) => {})