Skip to content

Commit c82d6a0

Browse files
authored
Merge pull request #438 from hotosm/feat-processing-status
Update the image processing status for a project.
2 parents 1e4c0ee + 7c720c1 commit c82d6a0

File tree

7 files changed

+116
-9
lines changed

7 files changed

+116
-9
lines changed

src/backend/app/db/db_models.py

+6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
UserRole,
2727
State,
2828
RegulatorApprovalStatus,
29+
ImageProcessingStatus,
2930
)
3031
from sqlalchemy.orm import (
3132
object_session,
@@ -155,6 +156,11 @@ class DbProject(Base):
155156
regulator_approval_status = cast(
156157
RegulatorApprovalStatus, Column(Enum(RegulatorApprovalStatus), nullable=True)
157158
)
159+
image_processing_status = cast(
160+
ImageProcessingStatus,
161+
Column(Enum(ImageProcessingStatus), default=ImageProcessingStatus.NOT_STARTED),
162+
) # status of image processing
163+
158164
regulator_comment = cast(str, Column(String, nullable=True))
159165
commenting_regulator_id = cast(
160166
str,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""image_processing_status
2+
3+
Revision ID: f78cde896334
4+
Revises: b18103ac4ab7
5+
Create Date: 2025-01-15 05:11:08.788485
6+
7+
"""
8+
9+
from typing import Sequence, Union
10+
11+
from alembic import op
12+
import sqlalchemy as sa
13+
14+
15+
# revision identifiers, used by Alembic.
16+
revision: str = "f78cde896334"
17+
down_revision: Union[str, None] = "b18103ac4ab7"
18+
branch_labels: Union[str, Sequence[str], None] = None
19+
depends_on: Union[str, Sequence[str], None] = None
20+
21+
22+
def upgrade() -> None:
23+
# ### commands auto generated by Alembic - please adjust! ###
24+
op.add_column(
25+
"projects",
26+
sa.Column(
27+
"image_processing_status",
28+
sa.Enum(
29+
"NOT_STARTED",
30+
"PROCESSING",
31+
"SUCCESS",
32+
"FAILED",
33+
name="imageprocessingstatus",
34+
),
35+
nullable=False,
36+
server_default=sa.text("'NOT_STARTED'"),
37+
),
38+
)
39+
40+
# ### end Alembic commands ###
41+
42+
43+
def downgrade() -> None:
44+
# ### commands auto generated by Alembic - please adjust! ###
45+
op.drop_column("projects", "image_processing_status")
46+
# ### end Alembic commands ###

src/backend/app/models/enums.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ class RegulatorApprovalStatus(IntEnum, Enum):
7474
REJECTED = 2
7575

7676

77+
class ImageProcessingStatus(IntEnum, Enum):
78+
"""Enum to describe all possible statys of a Image Processing for a Project"""
79+
80+
NOT_STARTED = 0
81+
PROCESSING = 1
82+
SUCCESS = 2
83+
FAILED = 3
84+
85+
7786
class ProjectVisibility(IntEnum, Enum):
7887
"""Enum describing task splitting type."""
7988

@@ -200,11 +209,11 @@ class EventType(str, Enum):
200209

201210

202211
class FlightMode(str, Enum):
203-
"""The flight mode of the drone.
204-
205-
The flight mode can be:
206-
- ``waylines``
207-
- ``waypoints``
212+
"""
213+
The flight mode of the drone.
214+
The flight mode can be:
215+
- ``waylines``
216+
- ``waypoints``
208217
"""
209218

210219
waylines = "waylines"

src/backend/app/projects/image_processing.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import shutil
66
from pathlib import Path
77
from app.tasks import task_logic
8-
from app.models.enums import State
8+
from app.models.enums import State, ImageProcessingStatus
99
from app.utils import timestamp
1010
from app.db import database
1111
from app.projects import project_logic
@@ -352,6 +352,7 @@ async def process_assets_from_odm(
352352
message=None,
353353
dtm_task_id=None,
354354
dtm_user_id=None,
355+
odm_status_code: Optional[int] = None,
355356
):
356357
"""
357358
Downloads results from ODM, reprojects the orthophoto, and uploads assets to S3.
@@ -443,6 +444,21 @@ async def process_assets_from_odm(
443444
conn, dtm_project_id, dtm_task_id, "assets_url", s3_path_url
444445
)
445446

447+
if not dtm_task_id:
448+
# Update the image processing status
449+
pool = await database.get_db_connection_pool()
450+
async with pool as pool_instance:
451+
async with pool_instance.connection() as conn:
452+
await project_logic.update_processing_status(
453+
conn,
454+
dtm_project_id,
455+
(
456+
ImageProcessingStatus.SUCCESS
457+
if odm_status_code == 40
458+
else ImageProcessingStatus.FAILED
459+
),
460+
)
461+
446462
except Exception as e:
447463
log.error(f"Error during processing for project {dtm_project_id}: {e}")
448464

src/backend/app/projects/project_logic.py

+28-3
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@
3838
create_placemarks,
3939
terrain_following_waylines,
4040
)
41-
from app.models.enums import FlightMode
41+
from app.models.enums import FlightMode, ImageProcessingStatus
4242

4343

4444
async def get_centroids(db: Connection):
4545
try:
4646
async with db.cursor(row_factory=dict_row) as cur:
47-
await cur.execute("""
47+
await cur.execute(
48+
"""
4849
SELECT
4950
p.id,
5051
p.slug,
@@ -61,7 +62,8 @@ async def get_centroids(db: Connection):
6162
task_events te ON t.id = te.task_id
6263
GROUP BY
6364
p.id, p.slug, p.name, p.centroid;
64-
""")
65+
"""
66+
)
6567
centroids = await cur.fetchall()
6668

6769
if not centroids:
@@ -335,6 +337,25 @@ async def process_drone_images(
335337
)
336338

337339

340+
async def update_processing_status(
341+
db: Connection, project_id: uuid.UUID, status: ImageProcessingStatus
342+
):
343+
print("status = ", status.name)
344+
"""
345+
Update the processing status to the specified status in the database.
346+
"""
347+
await db.execute(
348+
"""
349+
UPDATE projects
350+
SET image_processing_status = %(status)s
351+
WHERE id = %(project_id)s;
352+
""",
353+
{"status": status.name, "project_id": project_id},
354+
)
355+
await db.commit()
356+
return
357+
358+
338359
async def process_all_drone_images(
339360
project_id: uuid.UUID, tasks: list, user_id: str, db: Connection
340361
):
@@ -363,6 +384,10 @@ async def process_all_drone_images(
363384
webhook=webhook_url,
364385
)
365386

387+
# Update the processing status to 'IMAGE_PROCESSING_STARTED' in the database.
388+
await update_processing_status(db, project_id, ImageProcessingStatus.PROCESSING)
389+
return
390+
366391

367392
def get_project_info_from_s3(project_id: uuid.UUID, task_id: uuid.UUID):
368393
"""

src/backend/app/projects/project_routes.py

+3
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ async def odm_webhook_for_processing_whole_project(
504504
node_odm_url=settings.NODE_ODM_URL,
505505
dtm_project_id=dtm_project_id,
506506
odm_task_id=odm_task_id,
507+
odm_status=status["code"],
507508
)
508509

509510
return {"message": "Webhook received", "task_id": dtm_project_id}
@@ -541,6 +542,7 @@ async def odm_webhook_for_processing_a_single_task(
541542
message="Task completed.",
542543
dtm_task_id=dtm_task_id,
543544
dtm_user_id=dtm_user_id,
545+
odm_status=40,
544546
)
545547

546548
elif status["code"] == 30 and state_value != State.IMAGE_PROCESSING_FAILED:
@@ -563,6 +565,7 @@ async def odm_webhook_for_processing_a_single_task(
563565
message="Image processing failed.",
564566
dtm_task_id=dtm_task_id,
565567
dtm_user_id=dtm_user_id,
568+
odm_status_code=30,
566569
)
567570

568571
return {"message": "Webhook received", "task_id": odm_task_id}

src/backend/app/projects/project_schemas.py

+2
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class DbProject(BaseModel):
218218
requires_approval_from_regulator: Optional[bool] = False
219219
regulator_emails: Optional[List[EmailStr]] = None
220220
regulator_approval_status: Optional[str] = None
221+
image_processing_status: Optional[str] = None
221222
regulator_comment: Optional[str] = None
222223
commenting_regulator_id: Optional[str] = None
223224
author_id: Optional[str] = None
@@ -592,6 +593,7 @@ class ProjectInfo(BaseModel):
592593
requires_approval_from_regulator: Optional[bool] = False
593594
regulator_emails: Optional[List[EmailStr]] = None
594595
regulator_approval_status: Optional[str] = None
596+
image_processing_status: Optional[str] = None
595597
regulator_comment: Optional[str] = None
596598
commenting_regulator_id: Optional[str] = None
597599
author_name: Optional[str] = None

0 commit comments

Comments
 (0)