Skip to content

Commit b08b68d

Browse files
authored
Feature/pdct 1538 bulk import make async (#231)
* Add navigator-notify dependency and update python * Fix upgrade to python 3.10 issues * Add notification service * Make integration tests use the aws s3 mock * Rename * Fix test and change bcrypt version * Fix logging * Save local bulk import results to a dir that is ignored by git * Bump python in Dockerfile * Remove print
1 parent 8f410be commit b08b68d

File tree

13 files changed

+226
-55
lines changed

13 files changed

+226
-55
lines changed

.env.example

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@ SECRET_KEY=secret_test_key
88
API_HOST=http://navigator-admin-backend:8888
99

1010
# AWS
11-
INGEST_JSON_BUCKET=test_bucket
11+
BULK_IMPORT_BUCKET=skip
12+
AWS_ACCESS_KEY_ID=test
13+
_AWS_SECRET_ACCESS_KEY=test
14+
15+
# Slack Notifications
16+
SLACK_WEBHOOK_URL=skip

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ coverage.xml
5353
*.py,cover
5454
.hypothesis/
5555
.pytest_cache/
56+
bulk_import_results/
5657

5758
# Translations
5859
*.mo

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM python:3.9-slim
1+
FROM python:3.10-slim
22

33
WORKDIR /usr/src
44
ENV PYTHONPATH=/usr/src

app/api/api_v1/routers/ingest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ async def ingest(
251251
:param UploadFile new_data: file containing json representation of data to ingest.
252252
:return Json: json representation of the data to ingest.
253253
"""
254-
_LOGGER.info(f"Starting bulk import for corpus: {corpus_import_id}")
254+
_LOGGER.info(f"Received bulk import request for corpus: {corpus_import_id}")
255255

256256
try:
257257
content = await new_data.read()

app/clients/aws/s3bucket.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,16 @@ def upload_ingest_json_to_s3(
113113
:param str corpus_import_id: The import_id of the corpus the ingest data belongs to.
114114
:param dict[str, Any] json_data: The ingest json data to be uploaded to S3.
115115
"""
116-
ingest_upload_bucket = os.environ["INGEST_JSON_BUCKET"]
116+
_LOGGER.info(os.getenv("BULK_IMPORT_BUCKET", "Not there"))
117+
ingest_upload_bucket = os.environ["BULK_IMPORT_BUCKET"]
117118
current_timestamp = datetime.now().strftime("%m-%d-%YT%H:%M:%S")
119+
118120
filename = f"{ingest_id}-{corpus_import_id}-{current_timestamp}.json"
119121

120122
if ingest_upload_bucket == "skip":
121-
with open(filename, "w") as f:
122-
json.dump(data, f, indent=4)
123+
os.makedirs("bulk_import_results", exist_ok=True)
124+
with open(f"bulk_import_results/{filename}", "w") as file:
125+
json.dump(data, file, indent=4)
123126
return
124127

125128
s3_client = get_s3_client()

app/service/ingest.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import app.repository.family as family_repository
2424
import app.service.corpus as corpus
2525
import app.service.geography as geography
26+
import app.service.notification as notification_service
2627
import app.service.validation as validation
2728
from app.clients.aws.s3bucket import upload_ingest_json_to_s3
2829
from app.model.ingest import (
@@ -224,6 +225,10 @@ def import_data(data: dict[str, Any], corpus_import_id: str) -> None:
224225
:raises RepositoryError: raised on a database error.
225226
:raises ValidationError: raised should the data be invalid.
226227
"""
228+
notification_service.send_notification(
229+
f"🚀 Bulk import for corpus: {corpus_import_id} has started."
230+
)
231+
227232
ingest_uuid = uuid4()
228233
upload_ingest_json_to_s3(f"{ingest_uuid}-request", corpus_import_id, data)
229234

@@ -254,16 +259,18 @@ def import_data(data: dict[str, Any], corpus_import_id: str) -> None:
254259
_LOGGER.info("Saving events")
255260
result["events"] = save_events(event_data, corpus_import_id, db)
256261

257-
_LOGGER.info(
258-
f"Bulk import for corpus: {corpus_import_id} successfully completed"
259-
)
260-
261262
upload_ingest_json_to_s3(f"{ingest_uuid}-result", corpus_import_id, result)
262263

264+
notification_service.send_notification(
265+
f"🎉 Bulk import for corpus: {corpus_import_id} successfully completed."
266+
)
263267
except Exception as e:
264268
_LOGGER.error(
265269
f"Rolling back transaction due to the following error: {e}", exc_info=True
266270
)
267271
db.rollback()
272+
notification_service.send_notification(
273+
f"💥 Bulk import for corpus: {corpus_import_id} has failed."
274+
)
268275
finally:
269276
db.commit()

app/service/notification.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import logging
2+
import os
3+
4+
from notify.slack import slack_message
5+
6+
_LOGGER = logging.getLogger(__name__)
7+
_LOGGER.setLevel(logging.DEBUG)
8+
9+
10+
def send_notification(notification: str):
11+
try:
12+
_LOGGER.info(notification)
13+
if os.environ["SLACK_WEBHOOK_URL"] != "skip":
14+
slack_message(notification)
15+
except Exception as e:
16+
_LOGGER.error(f"Error sending notification caused by: {e}")

poetry.lock

+91-29
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[tool.poetry]
22
name = "admin_backend"
3-
version = "2.17.0"
3+
version = "2.17.1"
44
description = ""
55
authors = ["CPR-dev-team <[email protected]>"]
66
packages = [{ include = "app" }, { include = "tests" }]
77

88
[tool.poetry.dependencies]
9-
python = "^3.9"
9+
python = "^3.10"
1010
fastapi = "^0.103.0"
1111
fastapi-health = "^0.4.0"
1212
fastapi-pagination = "^0.12.9"
@@ -30,9 +30,11 @@ moto = "^4.2.2"
3030
types-sqlalchemy = "^1.4.53.38"
3131
urllib3 = "^1.26.17"
3232
db-client = { git = "https://github.com/climatepolicyradar/navigator-db-client.git", tag = "v3.8.18" }
33+
navigator-notify = { git = "https://github.com/climatepolicyradar/navigator-notify.git", tag = "v0.0.2-beta" }
34+
bcrypt = "4.0.1"
3335

3436
[tool.poetry.dev-dependencies]
35-
pre-commit = "^2.17.0"
37+
pre-commit = "^3.8.0"
3638
python-dotenv = "^0.19.2"
3739
pytest = "^8.3.2"
3840
pytest-dotenv = "^0.5.2"
@@ -67,5 +69,5 @@ exclude = "^/alembic/versions/"
6769
[tool.pyright]
6870
include = ["app", "tests"]
6971
exclude = ["**/__pycache__"]
70-
pythonVersion = "3.9"
72+
pythonVersion = "3.10"
7173
venv = "admin-backend"

0 commit comments

Comments
 (0)