Skip to content

Commit

Permalink
Merge pull request #438 from hotosm/feat-processing-status
Browse files Browse the repository at this point in the history
Update the image processing status for a project.
  • Loading branch information
nrjadkry authored Jan 15, 2025
2 parents 1e4c0ee + 7c720c1 commit c82d6a0
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/backend/app/db/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
UserRole,
State,
RegulatorApprovalStatus,
ImageProcessingStatus,
)
from sqlalchemy.orm import (
object_session,
Expand Down Expand Up @@ -155,6 +156,11 @@ class DbProject(Base):
regulator_approval_status = cast(
RegulatorApprovalStatus, Column(Enum(RegulatorApprovalStatus), nullable=True)
)
image_processing_status = cast(
ImageProcessingStatus,
Column(Enum(ImageProcessingStatus), default=ImageProcessingStatus.NOT_STARTED),
) # status of image processing

regulator_comment = cast(str, Column(String, nullable=True))
commenting_regulator_id = cast(
str,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""image_processing_status
Revision ID: f78cde896334
Revises: b18103ac4ab7
Create Date: 2025-01-15 05:11:08.788485
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "f78cde896334"
down_revision: Union[str, None] = "b18103ac4ab7"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"projects",
sa.Column(
"image_processing_status",
sa.Enum(
"NOT_STARTED",
"PROCESSING",
"SUCCESS",
"FAILED",
name="imageprocessingstatus",
),
nullable=False,
server_default=sa.text("'NOT_STARTED'"),
),
)

# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("projects", "image_processing_status")
# ### end Alembic commands ###
19 changes: 14 additions & 5 deletions src/backend/app/models/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ class RegulatorApprovalStatus(IntEnum, Enum):
REJECTED = 2


class ImageProcessingStatus(IntEnum, Enum):
"""Enum to describe all possible statys of a Image Processing for a Project"""

NOT_STARTED = 0
PROCESSING = 1
SUCCESS = 2
FAILED = 3


class ProjectVisibility(IntEnum, Enum):
"""Enum describing task splitting type."""

Expand Down Expand Up @@ -200,11 +209,11 @@ class EventType(str, Enum):


class FlightMode(str, Enum):
"""The flight mode of the drone.
The flight mode can be:
- ``waylines``
- ``waypoints``
"""
The flight mode of the drone.
The flight mode can be:
- ``waylines``
- ``waypoints``
"""

waylines = "waylines"
Expand Down
18 changes: 17 additions & 1 deletion src/backend/app/projects/image_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import shutil
from pathlib import Path
from app.tasks import task_logic
from app.models.enums import State
from app.models.enums import State, ImageProcessingStatus
from app.utils import timestamp
from app.db import database
from app.projects import project_logic
Expand Down Expand Up @@ -352,6 +352,7 @@ async def process_assets_from_odm(
message=None,
dtm_task_id=None,
dtm_user_id=None,
odm_status_code: Optional[int] = None,
):
"""
Downloads results from ODM, reprojects the orthophoto, and uploads assets to S3.
Expand Down Expand Up @@ -443,6 +444,21 @@ async def process_assets_from_odm(
conn, dtm_project_id, dtm_task_id, "assets_url", s3_path_url
)

if not dtm_task_id:
# Update the image processing status
pool = await database.get_db_connection_pool()
async with pool as pool_instance:
async with pool_instance.connection() as conn:
await project_logic.update_processing_status(
conn,
dtm_project_id,
(
ImageProcessingStatus.SUCCESS
if odm_status_code == 40
else ImageProcessingStatus.FAILED
),
)

except Exception as e:
log.error(f"Error during processing for project {dtm_project_id}: {e}")

Expand Down
31 changes: 28 additions & 3 deletions src/backend/app/projects/project_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@
create_placemarks,
terrain_following_waylines,
)
from app.models.enums import FlightMode
from app.models.enums import FlightMode, ImageProcessingStatus


async def get_centroids(db: Connection):
try:
async with db.cursor(row_factory=dict_row) as cur:
await cur.execute("""
await cur.execute(
"""
SELECT
p.id,
p.slug,
Expand All @@ -61,7 +62,8 @@ async def get_centroids(db: Connection):
task_events te ON t.id = te.task_id
GROUP BY
p.id, p.slug, p.name, p.centroid;
""")
"""
)
centroids = await cur.fetchall()

if not centroids:
Expand Down Expand Up @@ -335,6 +337,25 @@ async def process_drone_images(
)


async def update_processing_status(
db: Connection, project_id: uuid.UUID, status: ImageProcessingStatus
):
print("status = ", status.name)
"""
Update the processing status to the specified status in the database.
"""
await db.execute(
"""
UPDATE projects
SET image_processing_status = %(status)s
WHERE id = %(project_id)s;
""",
{"status": status.name, "project_id": project_id},
)
await db.commit()
return


async def process_all_drone_images(
project_id: uuid.UUID, tasks: list, user_id: str, db: Connection
):
Expand Down Expand Up @@ -363,6 +384,10 @@ async def process_all_drone_images(
webhook=webhook_url,
)

# Update the processing status to 'IMAGE_PROCESSING_STARTED' in the database.
await update_processing_status(db, project_id, ImageProcessingStatus.PROCESSING)
return


def get_project_info_from_s3(project_id: uuid.UUID, task_id: uuid.UUID):
"""
Expand Down
3 changes: 3 additions & 0 deletions src/backend/app/projects/project_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ async def odm_webhook_for_processing_whole_project(
node_odm_url=settings.NODE_ODM_URL,
dtm_project_id=dtm_project_id,
odm_task_id=odm_task_id,
odm_status=status["code"],
)

return {"message": "Webhook received", "task_id": dtm_project_id}
Expand Down Expand Up @@ -541,6 +542,7 @@ async def odm_webhook_for_processing_a_single_task(
message="Task completed.",
dtm_task_id=dtm_task_id,
dtm_user_id=dtm_user_id,
odm_status=40,
)

elif status["code"] == 30 and state_value != State.IMAGE_PROCESSING_FAILED:
Expand All @@ -563,6 +565,7 @@ async def odm_webhook_for_processing_a_single_task(
message="Image processing failed.",
dtm_task_id=dtm_task_id,
dtm_user_id=dtm_user_id,
odm_status_code=30,
)

return {"message": "Webhook received", "task_id": odm_task_id}
Expand Down
2 changes: 2 additions & 0 deletions src/backend/app/projects/project_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class DbProject(BaseModel):
requires_approval_from_regulator: Optional[bool] = False
regulator_emails: Optional[List[EmailStr]] = None
regulator_approval_status: Optional[str] = None
image_processing_status: Optional[str] = None
regulator_comment: Optional[str] = None
commenting_regulator_id: Optional[str] = None
author_id: Optional[str] = None
Expand Down Expand Up @@ -592,6 +593,7 @@ class ProjectInfo(BaseModel):
requires_approval_from_regulator: Optional[bool] = False
regulator_emails: Optional[List[EmailStr]] = None
regulator_approval_status: Optional[str] = None
image_processing_status: Optional[str] = None
regulator_comment: Optional[str] = None
commenting_regulator_id: Optional[str] = None
author_name: Optional[str] = None
Expand Down

0 comments on commit c82d6a0

Please sign in to comment.