Skip to content

Commit 565faa3

Browse files
Async (#8)
* use async/await for tiles * more async
1 parent 72acffa commit 565faa3

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ services:
1515
- GDAL_HTTP_MULTIPLEX=YES
1616
- GDAL_HTTP_VERSION=2
1717
- MODULE_NAME=titiler.main
18-
- MEMCACHE_HOST=0.0.0.0
18+
- MEMCACHE_HOST=memcached
1919
- MEMCACHE_USERNAME=myuser
20-
- MEMCACHE_USERNAME=mypassword
20+
- MEMCACHE_PASSWORD=mypassword
2121
- PORT=8000
2222
- PYTHONWARNINGS=ignore
2323
- VARIABLE_NAME=app

titiler/api/api_v1/endpoints/metadata.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import os
66
import re
7+
from functools import partial
78
from urllib.parse import urlencode
89

910
import numpy
@@ -13,12 +14,17 @@
1314
from fastapi import APIRouter, Query
1415
from starlette.requests import Request
1516
from starlette.responses import Response
16-
17+
from starlette.concurrency import run_in_threadpool
1718

1819
from titiler.core import config
1920
from titiler.models.mapbox import TileJSON
2021
from titiler.ressources.enums import ImageType
2122

23+
24+
_bounds = partial(run_in_threadpool, cogeo.bounds)
25+
_metadata = partial(run_in_threadpool, cogeo.metadata)
26+
_spatial_info = partial(run_in_threadpool, cogeo.spatial_info)
27+
2228
router = APIRouter()
2329

2430

@@ -37,7 +43,7 @@
3743
"tiles",
3844
}, # https://github.com/tiangolo/fastapi/issues/528#issuecomment-589659378
3945
)
40-
def tilejson(
46+
async def tilejson(
4147
request: Request,
4248
response: Response,
4349
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
@@ -66,7 +72,7 @@ def tilejson(
6672
else:
6773
tile_url = f"{scheme}://{host}/{{z}}/{{x}}/{{y}}@{tile_scale}x?{qs}"
6874

69-
meta = cogeo.spatial_info(url)
75+
meta = await _spatial_info(url)
7076
response.headers["Cache-Control"] = "max-age=3600"
7177
return dict(
7278
bounds=meta["bounds"],
@@ -81,19 +87,19 @@ def tilejson(
8187
@router.get(
8288
"/bounds", responses={200: {"description": "Return the bounds of the COG."}}
8389
)
84-
def bounds(
90+
async def bounds(
8591
response: Response,
8692
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
8793
):
8894
"""Handle /bounds requests."""
8995
response.headers["Cache-Control"] = "max-age=3600"
90-
return cogeo.bounds(url)
96+
return await _bounds(url)
9197

9298

9399
@router.get(
94100
"/metadata", responses={200: {"description": "Return the metadata of the COG."}}
95101
)
96-
def metadata(
102+
async def metadata(
97103
request: Request,
98104
response: Response,
99105
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
@@ -132,7 +138,7 @@ def metadata(
132138
hist_options.update(dict(range=list(map(float, histogram_range.split(",")))))
133139

134140
response.headers["Cache-Control"] = "max-age=3600"
135-
return cogeo.metadata(
141+
return await _metadata(
136142
url,
137143
pmin,
138144
pmax,

titiler/api/api_v1/endpoints/tiles.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44

55
import re
66
from io import BytesIO
7+
from functools import partial
78

89
import numpy
910

1011
from fastapi import APIRouter, Depends, Query, Path
12+
from starlette.concurrency import run_in_threadpool
1113

1214
from rio_tiler.io import cogeo
1315
from rio_tiler.colormap import get_colormap
@@ -20,9 +22,13 @@
2022
from titiler.ressources.common import drivers, mimetype
2123
from titiler.ressources.responses import TileResponse
2224

23-
router = APIRouter()
25+
26+
_tile = partial(run_in_threadpool, cogeo.tile)
27+
_render = partial(run_in_threadpool, render)
28+
_postprocess = partial(run_in_threadpool, utils.postprocess)
2429

2530

31+
router = APIRouter()
2632
responses = {
2733
200: {
2834
"content": {
@@ -44,16 +50,14 @@
4450
@router.get(r"/{z}/{x}/{y}\.{ext}", **tile_routes_params)
4551
@router.get(r"/{z}/{x}/{y}@{scale}x", **tile_routes_params)
4652
@router.get(r"/{z}/{x}/{y}@{scale}x\.{ext}", **tile_routes_params)
47-
def tile(
53+
async def tile(
4854
z: int = Path(..., ge=0, le=30, description="Mercator tiles's zoom level"),
4955
x: int = Path(..., description="Mercator tiles's column"),
5056
y: int = Path(..., description="Mercator tiles's row"),
5157
scale: int = Query(
5258
1, gt=0, lt=4, description="Tile size scale. 1=256x256, 2=512x512..."
5359
),
54-
ext: Optional[ImageType] = Query(
55-
None, description="Output image type. Default is auto."
56-
),
60+
ext: ImageType = Query(None, description="Output image type. Default is auto."),
5761
url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
5862
bidx: Optional[str] = Query(None, description="Coma (',') delimited band indexes"),
5963
nodata: Optional[Union[str, int, float]] = Query(
@@ -97,14 +101,14 @@ def tile(
97101
if nodata is not None:
98102
nodata = numpy.nan if nodata == "nan" else float(nodata)
99103

100-
tile, mask = cogeo.tile(
104+
tile, mask = await _tile(
101105
url, x, y, z, indexes=indexes, tilesize=tilesize, nodata=nodata
102106
)
103107

104108
if not ext:
105109
ext = ImageType.jpg if mask.all() else ImageType.png
106110

107-
tile = utils.postprocess(
111+
tile = await _postprocess(
108112
tile, mask, rescale=rescale, color_formula=color_formula
109113
)
110114

@@ -122,7 +126,7 @@ def tile(
122126
if ext == ImageType.tif:
123127
options = geotiff_options(x, y, z, tilesize=tilesize)
124128

125-
content = render(
129+
content = await _render(
126130
tile, mask, img_format=driver, colormap=color_map, **options
127131
)
128132

titiler/templates/index.html

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
<link href='https://api.mapbox.com/mapbox-assembly/v0.23.2/assembly.min.css' rel='stylesheet'>
1313
<script src='https://api.mapbox.com/mapbox-assembly/v0.23.2/assembly.js'></script>
14-
15-
<script src='https://npmcdn.com/@turf/turf/turf.min.js'></script>
1614
<script src="https://d3js.org/d3.v4.js"></script>
1715
<style>
1816
body {
@@ -680,10 +678,27 @@
680678
})
681679
})
682680

681+
const bboxPolygon = (bounds) => {
682+
return {
683+
'type': 'Feature',
684+
'geometry': {
685+
'type': 'Polygon',
686+
'coordinates': [[
687+
[bounds[0], bounds[1]],
688+
[bounds[2], bounds[1]],
689+
[bounds[2], bounds[3]],
690+
[bounds[0], bounds[3]],
691+
[bounds[0], bounds[1]]
692+
]]
693+
},
694+
'properties': {}
695+
}
696+
}
697+
683698
const addAOI = (bounds) => {
684699
const geojson = {
685700
type: "FeatureCollection",
686-
features: [turf.bboxPolygon(bounds)]
701+
features: [bboxPolygon(bounds)]
687702
}
688703

689704
map.addSource('aoi', {

0 commit comments

Comments
 (0)