Skip to content

Commit f354e61

Browse files
author
Phil Varner
authored
Merge pull request #67 from stac-utils/pv/refactor-classes-from-txn-to-core
move classes in transactions.py to core.py, to align with parent class organization
2 parents ba7409c + c3b146d commit f354e61

File tree

8 files changed

+152
-163
lines changed

8 files changed

+152
-163
lines changed

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ For changes, see the [Changelog](CHANGELOG.md).
88

99
## Development Environment Setup
1010

11+
To install the classes in your local Python env, run:
12+
13+
```shell
14+
cd stac_fastapi/elasticsearch
15+
pip install -e '.[dev]'
16+
```
17+
18+
### Pre-commit
19+
1120
Install [pre-commit](https://pre-commit.com/#install).
1221

1322
Prior to commit, run:
@@ -16,10 +25,6 @@ Prior to commit, run:
1625
pre-commit run --all-files`
1726
```
1827

19-
```shell
20-
cd stac_fastapi/elasticsearch
21-
pip install .[dev]
22-
```
2328

2429
## Building
2530

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ services:
3838
discovery.type: single-node
3939
network.host: 0.0.0.0
4040
http.port: 9200
41-
ES_JAVA_OPTS: -Xms512m -Xmx512m
41+
ES_JAVA_OPTS: -Xms512m -Xmx1g
4242
ports:
4343
- "9200:9200"

stac_fastapi/elasticsearch/setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
desc = f.read()
77

88
install_requires = [
9+
"fastapi",
910
"attrs",
1011
"pydantic[dotenv]",
1112
"stac_pydantic==2.0.*",

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
from stac_fastapi.api.app import StacApi
33
from stac_fastapi.api.models import create_get_request_model, create_post_request_model
44
from stac_fastapi.elasticsearch.config import ElasticsearchSettings
5-
from stac_fastapi.elasticsearch.core import CoreCrudClient
6-
from stac_fastapi.elasticsearch.extensions import QueryExtension
7-
from stac_fastapi.elasticsearch.indexes import IndexesClient
8-
from stac_fastapi.elasticsearch.session import Session
9-
from stac_fastapi.elasticsearch.transactions import (
5+
from stac_fastapi.elasticsearch.core import (
106
BulkTransactionsClient,
7+
CoreCrudClient,
118
TransactionsClient,
129
)
10+
from stac_fastapi.elasticsearch.extensions import QueryExtension
11+
from stac_fastapi.elasticsearch.indexes import IndexesClient
12+
from stac_fastapi.elasticsearch.session import Session
1313
from stac_fastapi.extensions.core import (
1414
ContextExtension,
1515
FieldsExtension,

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/core.py

Lines changed: 130 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,29 @@
22
import json
33
import logging
44
from datetime import datetime as datetime_type
5+
from datetime import timezone
56
from typing import List, Optional, Type, Union
67
from urllib.parse import urljoin
78

89
import attr
910
from fastapi import HTTPException
1011
from overrides import overrides
11-
12-
# from geojson_pydantic.geometries import Polygon
1312
from pydantic import ValidationError
1413
from stac_pydantic.links import Relations
1514
from stac_pydantic.shared import MimeTypes
1615

1716
from stac_fastapi.elasticsearch import serializers
17+
from stac_fastapi.elasticsearch.config import ElasticsearchSettings
1818
from stac_fastapi.elasticsearch.database_logic import DatabaseLogic
19+
from stac_fastapi.elasticsearch.serializers import CollectionSerializer, ItemSerializer
1920
from stac_fastapi.elasticsearch.session import Session
20-
21-
# from stac_fastapi.elasticsearch.types.error_checks import ErrorChecks
22-
from stac_fastapi.types.core import BaseCoreClient
21+
from stac_fastapi.extensions.third_party.bulk_transactions import (
22+
BaseBulkTransactionsClient,
23+
Items,
24+
)
25+
from stac_fastapi.types import stac as stac_types
26+
from stac_fastapi.types.core import BaseCoreClient, BaseTransactionsClient
27+
from stac_fastapi.types.links import CollectionLinks
2328
from stac_fastapi.types.stac import Collection, Collections, Item, ItemCollection
2429

2530
logger = logging.getLogger(__name__)
@@ -291,3 +296,123 @@ def post_search(self, search_request, **kwargs) -> ItemCollection:
291296
links=links,
292297
context=context_obj,
293298
)
299+
300+
301+
@attr.s
302+
class TransactionsClient(BaseTransactionsClient):
303+
"""Transactions extension specific CRUD operations."""
304+
305+
session: Session = attr.ib(default=attr.Factory(Session.create_from_env))
306+
database = DatabaseLogic()
307+
308+
@overrides
309+
def create_item(self, item: stac_types.Item, **kwargs) -> stac_types.Item:
310+
"""Create item."""
311+
base_url = str(kwargs["request"].base_url)
312+
313+
# If a feature collection is posted
314+
if item["type"] == "FeatureCollection":
315+
bulk_client = BulkTransactionsClient()
316+
processed_items = [
317+
bulk_client.preprocess_item(item, base_url) for item in item["features"]
318+
]
319+
return_msg = f"Successfully added {len(processed_items)} items."
320+
self.database.bulk_sync(processed_items)
321+
322+
return return_msg
323+
else:
324+
item = self.database.prep_create_item(item=item, base_url=base_url)
325+
self.database.create_item(item=item, base_url=base_url)
326+
return item
327+
328+
@overrides
329+
def update_item(self, item: stac_types.Item, **kwargs) -> stac_types.Item:
330+
"""Update item."""
331+
base_url = str(kwargs["request"].base_url)
332+
now = datetime_type.now(timezone.utc).isoformat().replace("+00:00", "Z")
333+
item["properties"]["updated"] = str(now)
334+
335+
self.database.check_collection_exists(collection_id=item["collection"])
336+
# todo: index instead of delete and create
337+
self.delete_item(item_id=item["id"], collection_id=item["collection"])
338+
self.create_item(item=item, **kwargs)
339+
340+
return ItemSerializer.db_to_stac(item, base_url)
341+
342+
@overrides
343+
def delete_item(
344+
self, item_id: str, collection_id: str, **kwargs
345+
) -> stac_types.Item:
346+
"""Delete item."""
347+
self.database.delete_item(item_id=item_id, collection_id=collection_id)
348+
return None
349+
350+
@overrides
351+
def create_collection(
352+
self, collection: stac_types.Collection, **kwargs
353+
) -> stac_types.Collection:
354+
"""Create collection."""
355+
base_url = str(kwargs["request"].base_url)
356+
collection_links = CollectionLinks(
357+
collection_id=collection["id"], base_url=base_url
358+
).create_links()
359+
collection["links"] = collection_links
360+
self.database.create_collection(collection=collection)
361+
362+
return CollectionSerializer.db_to_stac(collection, base_url)
363+
364+
@overrides
365+
def update_collection(
366+
self, collection: stac_types.Collection, **kwargs
367+
) -> stac_types.Collection:
368+
"""Update collection."""
369+
base_url = str(kwargs["request"].base_url)
370+
371+
self.database.find_collection(collection_id=collection["id"])
372+
self.delete_collection(collection["id"])
373+
self.create_collection(collection, **kwargs)
374+
375+
return CollectionSerializer.db_to_stac(collection, base_url)
376+
377+
@overrides
378+
def delete_collection(self, collection_id: str, **kwargs) -> stac_types.Collection:
379+
"""Delete collection."""
380+
self.database.delete_collection(collection_id=collection_id)
381+
return None
382+
383+
384+
@attr.s
385+
class BulkTransactionsClient(BaseBulkTransactionsClient):
386+
"""Postgres bulk transactions."""
387+
388+
session: Session = attr.ib(default=attr.Factory(Session.create_from_env))
389+
database = DatabaseLogic()
390+
391+
def __attrs_post_init__(self):
392+
"""Create es engine."""
393+
settings = ElasticsearchSettings()
394+
self.client = settings.create_client
395+
396+
def preprocess_item(self, item: stac_types.Item, base_url) -> stac_types.Item:
397+
"""Preprocess items to match data model."""
398+
item = self.database.prep_create_item(item=item, base_url=base_url)
399+
return item
400+
401+
@overrides
402+
def bulk_item_insert(
403+
self, items: Items, chunk_size: Optional[int] = None, **kwargs
404+
) -> str:
405+
"""Bulk item insertion using es."""
406+
request = kwargs.get("request")
407+
if request:
408+
base_url = str(request.base_url)
409+
else:
410+
base_url = ""
411+
412+
processed_items = [
413+
self.preprocess_item(item, base_url) for item in items.items.values()
414+
]
415+
416+
self.database.bulk_sync(processed_items)
417+
418+
return f"Successfully added {len(processed_items)} Items."

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/transactions.py

Lines changed: 0 additions & 142 deletions
This file was deleted.

stac_fastapi/elasticsearch/tests/clients/test_elasticsearch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
from tests.conftest import MockStarletteRequest
99

1010
from stac_fastapi.api.app import StacApi
11-
from stac_fastapi.elasticsearch.core import CoreCrudClient
12-
from stac_fastapi.elasticsearch.transactions import (
11+
from stac_fastapi.elasticsearch.core import (
1312
BulkTransactionsClient,
13+
CoreCrudClient,
1414
TransactionsClient,
1515
)
1616
from stac_fastapi.extensions.third_party.bulk_transactions import Items

stac_fastapi/elasticsearch/tests/conftest.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
from stac_fastapi.api.app import StacApi
99
from stac_fastapi.api.models import create_request_model
1010
from stac_fastapi.elasticsearch.config import ElasticsearchSettings
11-
from stac_fastapi.elasticsearch.core import CoreCrudClient
12-
from stac_fastapi.elasticsearch.extensions import QueryExtension
13-
from stac_fastapi.elasticsearch.indexes import IndexesClient
14-
from stac_fastapi.elasticsearch.transactions import (
11+
from stac_fastapi.elasticsearch.core import (
1512
BulkTransactionsClient,
13+
CoreCrudClient,
1614
TransactionsClient,
1715
)
16+
from stac_fastapi.elasticsearch.extensions import QueryExtension
17+
from stac_fastapi.elasticsearch.indexes import IndexesClient
1818
from stac_fastapi.extensions.core import (
1919
ContextExtension,
2020
FieldsExtension,

0 commit comments

Comments
 (0)