def execute_activity(experiment: Experiment, activity: Activity, configuration: Configuration, secrets: Secrets, dry: bool = False) -> Run: """ Low-level wrapper around the actual activity provider call to collect some meta data (like duration, start/end time, exceptions...) during the run. """ ref = activity.get("ref") if ref: activity = lookup_activity(ref) if not activity: raise ActivityFailed( "could not find referenced activity '{r}'".format(r=ref)) with controls(level="activity", experiment=experiment, context=activity, configuration=configuration, secrets=secrets) as control: pauses = activity.get("pauses", {}) pause_before = pauses.get("before") if pause_before: logger.info("Pausing before next activity for {d}s...".format( d=pause_before)) # only pause when not in dry-mode if not dry: time.sleep(pause_before) if activity.get("background"): logger.info("{t}: {n} [in background]".format( t=activity["type"].title(), n=activity.get("name"))) else: logger.info("{t}: {n}".format( t=activity["type"].title(), n=activity.get("name"))) start = datetime.utcnow() run = { "activity": activity.copy(), "output": None } result = None interrupted = False try: # only run the activity itself when not in dry-mode if not dry: result = run_activity(activity, configuration, secrets) run["output"] = result run["status"] = "succeeded" if result is not None: logger.debug(" => succeeded with '{r}'".format(r=result)) else: logger.debug(" => succeeded without any result value") except ActivityFailed as x: error_msg = str(x) run["status"] = "failed" run["output"] = result run["exception"] = traceback.format_exception(type(x), x, None) logger.error(" => failed: {x}".format(x=error_msg)) finally: # capture the end time before we pause end = datetime.utcnow() run["start"] = start.isoformat() run["end"] = end.isoformat() run["duration"] = (end - start).total_seconds() pause_after = pauses.get("after") if pause_after and not interrupted: logger.info("Pausing after activity for {d}s...".format( d=pause_after)) # only pause when not in dry-mode if not dry: time.sleep(pause_after) control.with_state(run) return run
def execute_activity( experiment: Experiment, activity: Activity, configuration: Configuration, secrets: Secrets, dry: Dry, ) -> Run: """ Low-level wrapper around the actual activity provider call to collect some meta data (like duration, start/end time, exceptions...) during the run. """ ref = activity.get("ref") if ref: activity = lookup_activity(ref) if not activity: raise ActivityFailed(f"could not find referenced activity '{ref}'") with controls( level="activity", experiment=experiment, context=activity, configuration=configuration, secrets=secrets, ) as control: dry = activity.get("dry", dry) pauses = activity.get("pauses", {}) pauses = substitute(pauses, configuration, secrets) pause_before = pauses.get("before") is_dry = False activity_type = activity["type"] if dry == Dry.ACTIONS: is_dry = activity_type == "action" elif dry == Dry.PROBES: is_dry = activity_type == "probe" elif dry == Dry.ACTIVITIES: is_dry = True if pause_before: logger.info(f"Pausing before next activity for {pause_before}s...") # pause when one of the dry flags are set if dry != Dry.PAUSE and not is_dry: time.sleep(pause_before) if activity.get("background"): logger.info("{t}: {n} [in background]".format( t=activity["type"].title(), n=activity.get("name"))) else: logger.info("{t}: {n}".format(t=activity["type"].title(), n=activity.get("name"))) start = datetime.utcnow() run = {"activity": activity.copy(), "output": None} result = None interrupted = False try: # pause when one of the dry flags are set if not is_dry: result = run_activity(activity, configuration, secrets) run["output"] = result run["status"] = "succeeded" if result is not None: logger.debug(f" => succeeded with '{result}'") else: logger.debug(" => succeeded without any result value") except ActivityFailed as x: error_msg = str(x) run["status"] = "failed" run["output"] = result run["exception"] = traceback.format_exception(type(x), x, None) logger.error(f" => failed: {error_msg}") finally: # capture the end time before we pause end = datetime.utcnow() run["start"] = start.isoformat() run["end"] = end.isoformat() run["duration"] = (end - start).total_seconds() pause_after = pauses.get("after") if pause_after and not interrupted: logger.info(f"Pausing after activity for {pause_after}s...") # pause when one of the dry flags are set if dry != Dry.PAUSE and not is_dry: time.sleep(pause_after) control.with_state(run) return run