def run_thread_loop(self):
        # HACK: Here we need to use the token_utils.parse_name, since the actual
        # event handler uses the context of the root_event, and that one is bounded
        # to the [root process] task.
        event_name_parsed = token_utils.parse_name(self.root_event.context,
                                                   self.root_event.task.name)

        LOG.info(yellow("Run  ") + yellow(event_name_parsed, bold=True))

        # FIXME: implement a decent test
        try:
            params = token_utils.matches(
                self.execution_message_event.re_expressions, event_name_parsed)

            for event_data in self.execution_message_event.code(
                    self.root_event.context, *params):
                self.enqueue_event(event=self.root_event.task,
                                   event_data=event_data)
        except Exception as e:
            LOG.error(red("Failed ") + red(event_name_parsed, bold=True))
            LOG.error(e)
            self.future.set_exception(e)
        else:
            LOG.info(green("Done ") + green(event_name_parsed, bold=True))
            self.future.set_result("__done")
Example #2
0
def raise_unhandled_exception(task_error: TaskError):
    log_path = get_folder(task_error.failed_event)

    LOG.error(
        red("Process execution failed. Unhandled error from ")
        + red(str(task_error.failed_event), bold=True)
    )

    if logredirect.is_enabled():
        stdout_file = os.path.join(log_path, "stdout")
        if os.path.isfile(stdout_file):
            with open(stdout_file) as f:
                LOG.error(white("STDOUT:", bold=True))
                LOG.error(white(f.read()))
        else:
            LOG.error(white("STDOUT:", bold=True) + white(" not found"))

        stderr_file = os.path.join(log_path, "stderr")
        if os.path.isfile(stderr_file):
            with open(stderr_file) as f:
                LOG.error(red("STDERR:"))
                LOG.error(red(f.read()))
        else:
            LOG.error(red("STDERR:", bold=True) + red(" not found"))

    LOG.error(red("Exception:", bold=True))
    LOG.error(red(task_error.error))

    sys.exit(1)
Example #3
0
def deep_copy_event(e: ActiveEvent) -> ActiveEvent:
    """
    We deepcopy everything except the workspace.
    :param e:
    :return:
    """
    try:
        workspace = e.context.workspace
        e.context.workspace = None
        result = copy.deepcopy(e)

        result.context.workspace = workspace

        return result
    except Exception as err:
        LOG.error(red("Unable to serialize token", bold=True))
        LOG.error(red(f"Data: {e.context.data._data}"))
        raise err
Example #4
0
def log_running_done(event: ActiveEvent, task_error=None):
    if event.loop_type in (ActiveLoopType.INITIAL,
                           ActiveLoopType.INITIAL_EMPTY):
        return

    if not task_error:
        LOG.info(green("Done ") + green(event.context.task_name, bold=True))
        return

    if task_error.failed_event != event:
        LOG.info(
            red("Terminated ") + red(event.context.task_name, bold=True) +
            red(" reason: ") + red(str(task_error.failed_event), bold=True))
        return

    LOG.info(red("Failed ") + red(event.context.task_name, bold=True))
Example #5
0
    def running_event(self, event: ActiveEvent, data: Any) -> None:
        if event.loop_type == ActiveLoopType.INITIAL:
            loop_controller.evaluate_initial_loop(event, self.clone_event)

            if event.loop_type == ActiveLoopType.INITIAL_EMPTY:
                self.events.transition(
                    event=event, state=ActiveEventState.ROUTING, data=event.context
                )
            else:
                self.events.transition(event=event, state=ActiveEventState.DONE)

            return

        if (
            event.deduplication_id is not None
            and event is self.events.get_waiting_deduplication(event=event)
        ):
            self.events.clear_waiting_deduplication(event=event)

        if (
            event.deduplication_id
            and isinstance(event.task, ProcessTask)
            and cast(ProcessTask, event.task).deduplicate
            and self.events.get_running_deduplication_event_count(event=event) > 1
        ):
            raise Exception(f"A deduplicated event is already running for {event}")

        # Since the data is potentially updated in WAIT, we need to ensure
        # the title matches the current data.
        event.context._update_title_from_data()

        # FIXME: probably this try/except should be longer than just the LOG
        try:
            LOG.info(yellow("Run  ") + yellow(event.context.task_name, bold=True))
        except Exception as e:
            raise Exception(f"Failure on {event.context.task_name}", e)

        # When we start running, we must register now timer events against the
        # schedule
        if isinstance(event.task, ProcessTask) and event.task.timer_events:
            timers: Set[ActiveTimer] = set()
            self.active_timers[event.token_id] = timers

            for timer_event in event.task.timer_events:
                timers.add(
                    create_active_timer(
                        fire_timer=self.fire_timer,
                        parent_token=event,
                        boundary_event_definition=timer_event,
                    )
                )

        if isinstance(event.task, Process):
            for start_task in event.task.start_events.values():
                if isinstance(start_task, ProcessTask) and start_task.loop:
                    # we start a loop by firing the loop events, and consume this event.
                    loop_controller.create_loop(
                        event, self.clone_event, start_task, parent_id=event.token_id
                    )
                else:
                    self.clone_event(event, start_task, parent_id=event.token_id)

            return None

        if isinstance(event.task, Task):
            if event.task.id not in self.tasks_impl:
                error_message = (
                    f"BUG: Task id {event.task.id} ({event.task.name}) "
                    f"not found in implementations {self.tasks_impl}"
                )

                LOG.critical(red(error_message, bold=True))
                raise Exception(error_message)

            future: Future[ExecutionToken] = self.pool.schedule(
                self.tasks_impl[event.task.id].invoke, args=(copy_event(event),)
            )
            self.assign_event_future(event, future)
            return None

        if isinstance(event.task, ScriptTask):
            future = self.pool.schedule(call_script_task, args=(copy_event(event),))
            self.assign_event_future(event, future)
            return None

        if isinstance(event.task, UserTask):
            future = Future()
            self.assign_event_future(event, future)

            assert self.ut_provider

            self.ut_provider.register_event(self, event)

            return None

        self.events.transition(
            event=event,
            state=ActiveEventState.ROUTING,
            data=event.context,
        )
Example #6
0
    def _print_process_task_mappings(self, *, process: Process, indent=0) -> None:
        print(
            "{indent}{type} {name} ({id})".format(
                indent="  " * indent,
                type=green("process")
                if process is self.adhesive_process.process
                else green("sub-process"),
                name=yellow(process.name, bold=True),
                id=white(process.id),
            )
        )

        indent += 1

        for task_id, task in process.tasks.items():
            task_impl = self.tasks_impl.get(task_id, None)

            if isinstance(task, Process):
                self._print_process_task_mappings(process=task, indent=indent + 1)
                continue

            if isinstance(task, Event) and not isinstance(task, MessageEvent):
                continue

            if isinstance(task, Gateway):
                continue

            if isinstance(task, ScriptTask):
                print(
                    "{indent}{type} {name} ({id}) -> {none}".format(
                        indent="  " * indent,
                        type=green("script"),
                        name=yellow(task.name, bold=True),
                        id=white(task.id),
                        none=cyan("<bpmn embedded script>", bold=True),
                    )
                )
                continue

            if not task_impl:
                print(
                    "{indent}{type} {name} ({id}) -> {none}".format(
                        indent="  " * indent,
                        type=green("task"),
                        name=yellow(task.name, bold=True),
                        id=white(task.id),
                        none=red("NONE", bold=False),
                    )
                )
                continue

            task_type = "task"

            if isinstance(task, ComplexGateway):
                task_type = "gateway"
            elif isinstance(task, UserTask):
                task_type = "user task"

            print(
                "{indent}{type} {name} ({id}) -> {fn} ({file})".format(
                    indent="  " * indent,
                    type=green(task_type),
                    name=yellow(task.name, bold=True),
                    id=white(task.id),
                    file=inspect.getfile(task_impl.code),
                    fn=cyan(task_impl.code.__name__, bold=True),
                )
            )