Example #1
0
def _execute_wfmodule_save(workflow: Workflow, wf_module: WfModule,
                           result: ProcessResult) -> OutputDelta:
    """
    Call wf_module.cache_render_result() and build OutputDelta.

    All this runs synchronously within a database lock. (It's a separate
    function so that when we're done awaiting it, we can continue executing in
    a context that doesn't use a database thread.)

    Raise UnneededExecution if the WfModule has changed in the interim.
    """
    # raises UnneededExecution
    with locked_wf_module(workflow, wf_module) as safe_wf_module:
        if safe_wf_module.notifications:
            stale_crr = safe_wf_module.get_stale_cached_render_result()
            if stale_crr is None:
                stale_result = None
            else:
                # Read entire old Parquet file, blocking
                stale_result = stale_crr.result
        else:
            stale_result = None

        safe_wf_module.cache_render_result(
            safe_wf_module.last_relevant_delta_id, result)

        if safe_wf_module.notifications and result != stale_result:
            safe_wf_module.has_unseen_notification = True
            safe_wf_module.save(update_fields=["has_unseen_notification"])
            return notifications.OutputDelta(safe_wf_module, stale_result,
                                             result)
        else:
            return None  # nothing to email
Example #2
0
def _execute_wfmodule_save(wf_module: WfModule, result: ProcessResult,
                           old_result: ProcessResult) -> Tuple:
    """
    Second database step of execute_wfmodule().

    Writes result (and maybe has_unseen_notification) to the WfModule in the
    database and returns a Tuple in this order:
        * cached_render_result: the return value of execute_wfmodule().
        * output_delta: if non-None, an OutputDelta to email to the Workflow
          owner.

    All this runs synchronously within a database lock. (It's a separate
    function so that when we're done awaiting it, we can continue executing in
    a context that doesn't use a database thread.)

    Raises UnneededExecution if the WfModule has changed in the interim.
    """
    with locked_wf_module(wf_module) as safe_wf_module:
        if (safe_wf_module.last_relevant_delta_id !=
                wf_module.last_relevant_delta_id):
            raise UnneededExecution

        cached_render_result = safe_wf_module.cache_render_result(
            safe_wf_module.last_relevant_delta_id, result)

        if safe_wf_module.notifications and result != old_result:
            safe_wf_module.has_unseen_notification = True
            output_delta = notifications.OutputDelta(safe_wf_module,
                                                     old_result, result)
        else:
            output_delta = None

        # Save safe_wf_module, not wf_module, because we know we've only
        # changed the cached_render_result columns. (We know because we
        # locked the row before fetching it.) `wf_module.save()` might
        # overwrite some newer values.
        safe_wf_module.save()

        return (cached_render_result, output_delta)