-
Notifications
You must be signed in to change notification settings - Fork 7
/
OffsetStrategy.ts
91 lines (81 loc) · 2.99 KB
/
OffsetStrategy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)
// SPDX-License-Identifier: Apache-2.0
import { FeatureLike } from "ol/Feature";
import { LoadFeatureOptions, loadPages } from "./createVectorSource";
import { createOffsetURL, getNextURL } from "./requestUtils";
import { HttpService } from "@open-pioneer/http";
/** @internal */
export interface CollectionInfos {
/** True if features can be requested in pages using offset & limit parameters. */
supportsOffsetStrategy: boolean;
}
export async function getCollectionInfos(
collectionsItemsUrl: string,
httpService: HttpService
): Promise<CollectionInfos> {
const infos: CollectionInfos = {
supportsOffsetStrategy: false
};
const url = new URL(collectionsItemsUrl);
url.searchParams.set("limit", "1");
url.searchParams.set("f", "json");
const response = await httpService.fetch(url.toString(), {
headers: {
Accept: "application/geo+json"
}
});
if (response.status !== 200) {
throw new Error(`Failed to probe collection information (status code ${response.status})`);
}
const jsonResp = await response.json();
const nextUrl = getNextURL(jsonResp.links);
if (!nextUrl) {
return infos;
}
const parsedURL = new URL(nextUrl);
const hasOffset = parsedURL.searchParams.has("offset");
infos.supportsOffsetStrategy = hasOffset;
return infos;
}
/** @internal */
export async function loadAllFeaturesWithOffset(
options: LoadFeatureOptions
): Promise<FeatureLike[]> {
const { fullURL, featureFormat, signal, addFeatures, queryFeatures } = options;
const pageSize = options.limit;
const maxConcurrency = options.maxConcurrentRequests;
let startOffset = 0;
let currentUrl: string | undefined = fullURL;
const allFeatures: FeatureLike[] = [];
let totalFeatures: number | undefined;
while (currentUrl) {
let pagesInIteration: number;
if (totalFeatures == undefined) {
// We don't know the actual size of the result set yet.
pagesInIteration = maxConcurrency;
} else {
pagesInIteration = Math.ceil((totalFeatures - startOffset) / pageSize);
}
pagesInIteration = Math.max(1, Math.min(pagesInIteration, maxConcurrency));
const urls: string[] = [];
for (let page = 0; page < pagesInIteration; ++page) {
urls.push(createOffsetURL(fullURL, startOffset, pageSize));
startOffset += pageSize;
}
const allFeatureResp = await loadPages(
urls,
featureFormat,
options.httpService,
signal,
addFeatures,
queryFeatures
);
allFeatures.push(...allFeatureResp.features);
currentUrl = allFeatureResp.nextURL;
if (allFeatureResp.numberMatched != null) {
totalFeatures = allFeatureResp.numberMatched;
}
}
while (currentUrl !== undefined);
return allFeatures;
}