Skip to content
Open
10 changes: 8 additions & 2 deletions api/app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from contextlib import asynccontextmanager
from pathlib import Path

Expand All @@ -20,7 +21,8 @@
@asynccontextmanager
async def lifespan(app: Litestar):
await open_pool()
await ensure_schema()
if os.getenv("OSMSG_SKIP_SCHEMA_ENSURE", "").lower() not in {"1", "true", "yes"}:
await ensure_schema()
try:
yield
finally:
Expand Down Expand Up @@ -49,7 +51,11 @@ async def health() -> HealthResponse:
app = Litestar(
route_handlers=[home, health, v1_router],
lifespan=[lifespan],
cors_config=CORSConfig(allow_origins=["*"]),
cors_config=CORSConfig(
allow_origins=["*"],
allow_methods=["GET", "OPTIONS"],
allow_headers=["*"],
),
openapi_config=OpenAPIConfig(
title="OSMSG API",
version="1.0.0",
Expand Down
22 changes: 22 additions & 0 deletions api/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import TypeVar

from litestar.pagination import OffsetPagination
from pydantic import BaseModel, Field

RowT = TypeVar("RowT")


class PaginationParams(BaseModel):
limit: int = Field(default=100, ge=1, le=1000)
offset: int = Field(default=0, ge=0)

@property
def query_limit(self) -> int:
return self.limit + 1


def paginate_items(rows: list[RowT], params: PaginationParams) -> OffsetPagination[RowT]:
has_next = len(rows) > params.limit
items = rows[: params.limit]
total = params.offset + len(items) + int(has_next)
return OffsetPagination(items=items, limit=params.limit, offset=params.offset, total=total)
18 changes: 12 additions & 6 deletions api/pg_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
PG_SCHEMA = """
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE TABLE IF NOT EXISTS users (
uid BIGINT PRIMARY KEY,
username TEXT NOT NULL
Expand All @@ -10,10 +9,17 @@
created_at TIMESTAMPTZ,
hashtags TEXT[],
editor TEXT,
geom GEOMETRY(POLYGON)
min_lon DOUBLE PRECISION,
min_lat DOUBLE PRECISION,
max_lon DOUBLE PRECISION,
max_lat DOUBLE PRECISION
);
CREATE INDEX IF NOT EXISTS idx_changesets_created_at ON changesets USING BTREE (created_at);
CREATE INDEX IF NOT EXISTS idx_changesets_hashtags ON changesets USING GIN (hashtags);
CREATE INDEX IF NOT EXISTS idx_changesets_editor ON changesets USING BTREE (editor);
CREATE INDEX IF NOT EXISTS idx_changesets_bbox ON changesets USING GIST (
box(point(min_lon, min_lat), point(max_lon, max_lat))
);
CREATE INDEX IF NOT EXISTS idx_changesets_created_at ON changesets(created_at);
CREATE INDEX IF NOT EXISTS idx_changesets_geom ON changesets USING GIST (geom);
CREATE TABLE IF NOT EXISTS changeset_stats (
changeset_id BIGINT NOT NULL REFERENCES changesets(changeset_id),
seq_id BIGINT NOT NULL,
Expand All @@ -32,8 +38,8 @@
tag_stats JSONB,
PRIMARY KEY (seq_id, changeset_id)
);
CREATE INDEX IF NOT EXISTS idx_changeset_stats_uid ON changeset_stats(uid);
CREATE INDEX IF NOT EXISTS idx_changeset_stats_changeset_id ON changeset_stats(changeset_id);
CREATE INDEX IF NOT EXISTS idx_changeset_stats_uid ON changeset_stats USING BTREE (uid);
CREATE INDEX IF NOT EXISTS idx_changeset_stats_changeset_id ON changeset_stats USING BTREE (changeset_id);
CREATE TABLE IF NOT EXISTS state (
source_url TEXT PRIMARY KEY,
last_seq BIGINT NOT NULL,
Expand Down
Loading
Loading