class NotificationAspect {

    @AfterReturning(
        pointcut =
            "execution(* com.epam.pipeline.manager.pipeline.PipelineRunManager.runPipeline(..)) || " +
            "execution(* com.epam.pipeline.manager.pipeline.PipelineRunManager.runCmd(..)) ||" +
            "execution(* com.epam.pipeline.manager.pipeline.PipelineRunCRUDService.updateRunStatus(" +
            "com.epam.pipeline.entity.pipeline.PipelineRun)) || " +
            "execution(* com.epam.pipeline.manager.pipeline.PipelineRunManager.updatePipelineStatusIfNotFinal(..)) ||" +
            "execution(* com.epam.pipeline.manager.pipeline.PipelineRunManager"
            + ".updatePipelineStatusIfNotFinalExternal(..)))",
        returning = "run"
        )
    @Async("notificationsExecutor")
    public void notifyRunStatusChanged(JoinPoint joinPoint, PipelineRun run) {
        final RunStatus newStatus = RunStatus.builder()
                .runId(run.getId()).status(run.getStatus())
                .timestamp(DateUtils.nowUTC())
                .reason(run.getStateReasonMessage())
                .build();
        runStatusManager.saveStatus(newStatus);
        if (run.isTerminating()) {
            LOGGER.debug("Won't send a notification [{} {}: {}] (filtered by status type)", run.getPipelineName(),
                          run.getVersion(), run.getStatus());
            return;
        }

        if (run.getPipelineName() == null) {
            if (run.getPipelineId() != null) {
                Pipeline pipeline = pipelineManager.load(run.getPipelineId());
                run.setPipelineName(pipeline.getName());
            } else {
                run.setPipelineName("pipeline");
            }
        }

        LOGGER.debug("Notify all about pipelineRun status changed {} {} {}: {}",
                     run.getPodId(), run.getPipelineName(), run.getVersion(), run.getStatus());
        notificationManager.notifyRunStatusChanged(run);
    }

}