Skip to content

Commit

Permalink
Feature/acknowledged by showed in task logs (#721)
Browse files Browse the repository at this point in the history
* Create function to save acknowledged task completion in logs

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Save ack by in logs

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Remove unused import

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Use instance of Phases instead of dict in get task logs functions

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Get phases key correctly and add comments to describe changes

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Add comment to describe code changes

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Lint warning and erros fixed

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Unused import

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* remove the construction of task_repo

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Revert changes

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Adding try catch to handle error

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Lint fix

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Remove instance of TaskRepository and pass it as params in Alert

Signed-off-by: angatupyry <fierrofenix@gmail.com>

* Add task repository dependency in alert repository

Signed-off-by: angatupyry <fierrofenix@gmail.com>

---------

Signed-off-by: angatupyry <fierrofenix@gmail.com>
  • Loading branch information
Angatupyry authored Jun 30, 2023
1 parent ca0e27e commit 3f563d3
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 8 deletions.
26 changes: 22 additions & 4 deletions packages/api-server/api_server/repositories/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@
from api_server.logger import logger
from api_server.models import User
from api_server.models import tortoise_models as ttm
from api_server.repositories.tasks import TaskRepository, task_repo_dep


class AlertRepository:
def __init__(self, user: User):
def __init__(self, user: User, task_repo: Optional[TaskRepository]):
self.user = user
self.task_repo = (
task_repo if task_repo is not None else TaskRepository(self.user)
)

async def get_all_alerts(self) -> List[ttm.AlertPydantic]:
alerts = await ttm.Alert.all()
Expand Down Expand Up @@ -71,17 +75,31 @@ async def acknowledge_alert(self, alert_id: str) -> Optional[ttm.AlertPydantic]:
# https://github.com/tortoise/tortoise-orm/pull/1131. This is a
# temporary workaround.
ack_alert._custom_generated_pk = True # pylint: disable=W0212
unix_millis_acknowledged_time = round(ack_time.timestamp() * 1e3)
ack_alert.update_from_dict(
{
"acknowledged_by": self.user.username,
"unix_millis_acknowledged_time": round(ack_time.timestamp() * 1e3),
"unix_millis_acknowledged_time": unix_millis_acknowledged_time,
}
)
await ack_alert.save()

# Save in logs who was the user that acknowledged the task
try:
await self.task_repo.save_log_acknowledged_task_completion(
alert.id, self.user.username, unix_millis_acknowledged_time
)
except Exception as e:
raise RuntimeError(
f"Error in save_log_acknowledged_task_completion {e}"
) from e

await alert.delete()
ack_alert_pydantic = await ttm.AlertPydantic.from_tortoise_orm(ack_alert)
return ack_alert_pydantic


def alert_repo_dep(user: User = Depends(user_dep)):
return AlertRepository(user)
def alert_repo_dep(
user: User = Depends(user_dep), task_repo: TaskRepository = Depends(task_repo_dep)
):
return AlertRepository(user, task_repo)
61 changes: 58 additions & 3 deletions packages/api-server/api_server/repositories/tasks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys
from datetime import datetime
from typing import Dict, List, Optional, Sequence, Tuple, cast

Expand All @@ -18,8 +19,11 @@
User,
)
from api_server.models import tortoise_models as ttm
from api_server.models.rmf_api.log_entry import Tier
from api_server.models.rmf_api.task_state import Category, Id, Phase
from api_server.models.tortoise_models import TaskState as DbTaskState
from api_server.query import add_pagination
from api_server.rmf_io import task_events


class TaskRepository:
Expand Down Expand Up @@ -94,12 +98,12 @@ async def get_task_log(
return None
phases = {}
for db_phase in result.phases:
phase = {}
phase["log"] = [LogEntry(**dict(x)) for x in db_phase.log]
phase = Phases(log=None, events=None)
phase.log = [LogEntry(**dict(x)) for x in db_phase.log]
events = {}
for db_event in db_phase.events:
events[db_event.event] = [LogEntry(**dict(x)) for x in db_event.log]
phase["events"] = events
phase.events = events
phases[db_phase.phase] = phase
return TaskEventLog.construct(
task_id=result.task_id,
Expand Down Expand Up @@ -153,6 +157,57 @@ async def _saveTaskLogs(
text=log.text,
)

async def save_log_acknowledged_task_completion(
self, task_id: str, acknowledged_by: str, unix_millis_acknowledged_time: int
) -> None:
async with in_transaction():
task_logs = await self.get_task_log(task_id, (0, sys.maxsize))
task_state = await self.get_task_state(task_id=task_id)
# A try could be used here to avoid using so many "ands"
# but the configured lint suggests comparing that no value is None
if task_logs and task_state and task_logs.phases and task_state.phases:
# The next phase key value matches in both `task_logs` and `task_state`.
# It is the same whether it is obtained from `task_logs` or from `task_state`.
# In this case, it is obtained from `task_logs` and is also used to assign the next
# phase in `task_state`.
next_phase_key = str(int(list(task_logs.phases)[-1]) + 1)
else:
raise ValueError("Phases can't be null")

event = LogEntry(
seq=0,
tier=Tier.warning,
unix_millis_time=unix_millis_acknowledged_time,
text=f"Task completion acknowledged by {acknowledged_by}",
)
task_logs.phases = {
**task_logs.phases,
next_phase_key: Phases(log=[], events={"0": [event]}),
}

await self.save_task_log(task_logs)

task_state.phases = {
**task_state.phases,
next_phase_key: Phase(
id=Id(__root__=next_phase_key),
category=Category(__root__="Task completed"),
detail=None,
unix_millis_start_time=None,
unix_millis_finish_time=None,
original_estimate_millis=None,
estimate_millis=None,
final_event_id=None,
events=None,
skip_requests=None,
),
}

await self.save_task_state(task_state)
# Notifies observers of the next task_state value to correctly display the title of the
# logs when acknowledged by a user without reloading the page.
task_events.task_states.on_next(task_state)

async def save_task_log(self, task_log: TaskEventLog) -> None:
async with in_transaction():
db_task_log = (
Expand Down
2 changes: 1 addition & 1 deletion packages/api-server/api_server/routes/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
logger = base_logger.getChild("RmfGatewayApp")
user: mdl.User = mdl.User(username="__rmf_internal__", is_admin=True)
task_repo = TaskRepository(user)
alert_repo = AlertRepository(user)
alert_repo = AlertRepository(user, task_repo)


def log_phase_has_error(phase: mdl.Phases) -> bool:
Expand Down

0 comments on commit 3f563d3

Please sign in to comment.