Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add aiocache for tile cache #207

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ dependencies = [
"pygeofilter>=0.2.0,<0.3.0",
"ciso8601~=2.3",
"starlette-cramjam>=0.4,<0.5",
"aiocache",
]

[project.optional-dependencies]
Expand Down
15 changes: 15 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import os
from contextlib import asynccontextmanager
from typing import Any, Dict

import aiocache
import psycopg
import pytest
from pytest_postgresql.janitor import DatabaseJanitor
Expand Down Expand Up @@ -101,6 +103,17 @@ def database_url(database):
return db_url


def _setup_cache():
config: Dict[str, Any] = {
"cache": "aiocache.SimpleMemoryCache",
"serializer": {
"class": "aiocache.serializers.PickleSerializer",
},
"ttl": 100,
}
aiocache.caches.set_config({"default": config})


def create_tipg_app(
postgres_settings: PostgresSettings,
db_settings: DatabaseSettings,
Expand Down Expand Up @@ -134,6 +147,7 @@ async def lifespan(app: FastAPI):
spatial_extent=db_settings.spatial_extent,
datetime_extent=db_settings.datetime_extent,
)
_setup_cache()
yield
await close_db_connection(app)

Expand Down Expand Up @@ -175,6 +189,7 @@ def app(database_url, monkeypatch):
monkeypatch.setenv("TIPG_DEFAULT_MINZOOM", str(5))
monkeypatch.setenv("TIPG_DEFAULT_MAXZOOM", str(12))

monkeypatch.setenv("TIPG_CACHE_DISABLE", "TRUE")
monkeypatch.setenv("TIPG_DEBUG", "TRUE")

from tipg.main import app, db_settings, postgres_settings
Expand Down
12 changes: 12 additions & 0 deletions tipg/collections.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""tipg.dbmodel: database events."""

import datetime
import hashlib
import json
import re
from functools import lru_cache
from typing import Any, Dict, List, Optional, Tuple, TypedDict, Union

from aiocache import cached
from buildpg import RawDangerous as raw
from buildpg import asyncpg, clauses
from buildpg import funcs as pg_funcs
Expand Down Expand Up @@ -794,6 +797,14 @@ async def features(
prev=max(offset - limit, 0) if offset else None,
)

@cached(
key_builder=lambda _f,
self,
pool,
tms,
tile,
**kwargs: f"{self.id}-{tms.id}-{tile.x}-{tile.y}-{tile.z}-{hashlib.md5(json.dumps(kwargs, sort_keys=True).encode('utf-8')).hexdigest()}",
)
async def get_tile(
self,
*,
Expand All @@ -813,6 +824,7 @@ async def get_tile(
limit: Optional[int] = None,
):
"""Build query to get Vector Tile."""
print(f"{tile.x}-{tile.y}-{tile.z}")
limit = limit or mvt_settings.max_features_per_tile

geometry_column = self.get_geometry_column(geom)
Expand Down
5 changes: 4 additions & 1 deletion tipg/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
from tipg.errors import MissingGeometryColumn, NoPrimaryKey, NotFound
from tipg.resources.enums import MediaType
from tipg.resources.response import GeoJSONResponse, SchemaJSONResponse, orjsonDumps
from tipg.settings import FeaturesSettings, MVTSettings, TMSSettings
from tipg.settings import CacheSettings, FeaturesSettings, MVTSettings, TMSSettings

from fastapi import APIRouter, Depends, Path, Query
from fastapi.responses import ORJSONResponse
Expand All @@ -59,6 +59,7 @@
tms_settings = TMSSettings()
mvt_settings = MVTSettings()
features_settings = FeaturesSettings()
cache_settings = CacheSettings()


jinja2_env = jinja2.Environment(
Expand Down Expand Up @@ -1604,6 +1605,8 @@ async def collection_get_tile(
limit=limit,
geom=geom_column,
dt=datetime_column,
cache_write=cache_settings.disable is False,
cache_read=cache_settings.disable is False,
)

return Response(bytes(tile), media_type=MediaType.mvt.value)
Expand Down
21 changes: 20 additions & 1 deletion tipg/main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""tipg app."""

from contextlib import asynccontextmanager
from typing import Any, List
from typing import Any, Dict, List

import aiocache
import jinja2

from tipg import __version__ as tipg_version
Expand All @@ -13,6 +14,7 @@
from tipg.middleware import CacheControlMiddleware, CatalogUpdateMiddleware
from tipg.settings import (
APISettings,
CacheSettings,
CustomSQLSettings,
DatabaseSettings,
PostgresSettings,
Expand All @@ -28,6 +30,21 @@
postgres_settings = PostgresSettings()
db_settings = DatabaseSettings()
custom_sql_settings = CustomSQLSettings()
cache_settings = CacheSettings()


def setup_cache():
"""Setup aiocache."""
config: Dict[str, Any] = {
"cache": "aiocache.SimpleMemoryCache",
"serializer": {
"class": "aiocache.serializers.PickleSerializer",
},
}
if cache_settings.ttl is not None:
config["ttl"] = cache_settings.ttl

aiocache.caches.set_config({"default": config})


@asynccontextmanager
Expand Down Expand Up @@ -56,6 +73,8 @@ async def lifespan(app: FastAPI):
datetime_extent=db_settings.datetime_extent,
)

setup_cache()

yield

# Close the Connection Pool
Expand Down
16 changes: 16 additions & 0 deletions tipg/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,19 @@ def sql_files(self) -> Optional[List[pathlib.Path]]:
return list(self.custom_sql_directory.glob("*.sql"))

return None


class CacheSettings(BaseSettings):
"""Cache settings"""

# TTL of the cache in seconds
ttl: int = 300

# Whether or not caching is enabled
disable: bool = False

model_config = {
"env_prefix": "TIPG_CACHE_",
"env_file": ".env",
"extra": "ignore",
}
Loading