Source code for autowisp.browser_interface.processing.progress_view

"""Define the view displaying the current processing progress."""

import logging
from socket import getfqdn
import os
from datetime import datetime

from sqlalchemy import select, sql
from psutil import pid_exists
from django.shortcuts import render

from autowisp.database.interface import start_db_session
from autowisp.database.user_interface import (
    get_processing_sequence,
    get_progress,
    list_channels,
)
from autowisp.error_render import (
    error_counts_by_step,
    open_error_count_for_steps,
)

# False positive
# pylint: disable=no-name-in-module
from autowisp.database.data_model import ImageProcessingProgress, PipelineRun

# pylint: enable=no-name-in-module

from .log_views import datetime_fmt

logger = logging.getLogger(__name__)


[docs] def progress(request, await_start=-1): # pylint: disable=too-many-locals """Display the current processing progress.""" print(f"Generating progress page with await start: {await_start}") context = {"await_start": await_start + 1} if 0 <= await_start < 10: context = { "await_start": await_start + 1, "running": True, "refresh_seconds": 6, } else: context = { "await_start": -1, "running": False, "refresh_seconds": 0, } with start_db_session() as db_session: context["channels"] = sorted(list_channels(db_session)) channel_index = { channel: i for i, channel in enumerate(context["channels"]) } processing_sequence = get_processing_sequence(db_session) error_by_step = error_counts_by_step(db_session) # Drives the colour of the Start Processing button: open pipeline + # step errors (BUI errors excluded) mean "errors pending". context["gate_error_count"] = open_error_count_for_steps([], db_session) context["progress"] = [ [ step.name.split("_"), imtype.name, [[0, 0, 0, []] for _ in context["channels"]], [], error_by_step.get(step.name, 0), ] for step, imtype in processing_sequence ] for (step, imtype), destination in zip( processing_sequence, context["progress"] ): final, pending, by_status = get_progress( step, imtype.id, 0, db_session ) for channel, status, count in final: destination[2][channel_index[channel]][ 0 if status > 0 else 1 ] = (count or 0) for channel, count in pending: destination[2][channel_index[channel]][2] = count or 0 for channel, status, count in by_status: destination[2][channel_index[channel]][3].append( (status, (count or 0)) ) destination[3] = [ ( record[0], record[1].strftime(datetime_fmt) if record[1] else "-", record[2].strftime(datetime_fmt) if record[2] else "-", ) for record in db_session.execute( select( ImageProcessingProgress.id, ImageProcessingProgress.started, ImageProcessingProgress.finished, ).where( ImageProcessingProgress.step_id == step.id, ImageProcessingProgress.image_type_id == imtype.id, ) ).all() ] for check_running in db_session.scalars( select(PipelineRun).filter_by(finished=None, host=getfqdn()) ).all(): elapsed_time = datetime.now() - check_running.started if ( pid_exists(check_running.process_id) and check_running.process_id != os.getpid() or (elapsed_time.days < 0 and elapsed_time.seconds <= 60) ): logger.info( "Calibration process with ID %s still exists.", check_running.process_id, ) context["running"] = True context["refresh_seconds"] = 5 context["await_start"] = -1 else: logger.info("Marking %s as finished", check_running) check_running.finished = ( sql.func.now() # pylint: disable=not-callable ) # Get selected steps from session if processing selected_tokens = set() if context["running"] and "selected_step_tokens" in request.session: selected_tokens = set(request.session["selected_step_tokens"]) context["selected_tokens"] = selected_tokens return render(request, "processing/progress.html", context)