def call_xtriggers_async(self, itask: TaskProxy): """Call itask's xtrigger functions via the process pool... ...if previous call not still in-process and retry period is up. Args: itask: task proxy to check. """ for label, sig, ctx, _ in self._get_xtrigs(itask, unsat_only=True): if sig.startswith("wall_clock"): # Special case: quick synchronous clock check. if 'absolute_as_seconds' not in ctx.func_kwargs: ctx.func_kwargs.update( { 'point_as_seconds': itask.get_point_as_seconds() } ) if wall_clock(*ctx.func_args, **ctx.func_kwargs): itask.state.xtriggers[label] = True self.sat_xtrig[sig] = {} self.data_store_mgr.delta_task_xtrigger(sig, True) LOG.info('xtrigger satisfied: %s = %s', label, sig) continue # General case: potentially slow asynchronous function call. if sig in self.sat_xtrig: if not itask.state.xtriggers[label]: itask.state.xtriggers[label] = True res = {} for key, val in self.sat_xtrig[sig].items(): res["%s_%s" % (label, key)] = val if res: xtrigger_env = [{'environment': {key: val}} for key, val in res.items()] self.broadcast_mgr.put_broadcast( [str(itask.point)], [itask.tdef.name], xtrigger_env ) continue if sig in self.active: # Already waiting on this result. continue now = time() if sig in self.t_next_call and now < self.t_next_call[sig]: # Too soon to call this one again. continue self.t_next_call[sig] = now + ctx.intvl # Queue to the process pool, and record as active. self.active.append(sig) self.proc_pool.put_command(ctx, self.callback)
def satisfy_xtriggers(self, itask: TaskProxy): """Attempt to satisfy itask's xtriggers. Args: itask (TaskProxy): TaskProxy """ for label, sig, ctx, _ in self._get_xtrigs(itask, unsat_only=True): if sig.startswith("wall_clock"): # Special case: synchronous clock check. ctx.func_kwargs.update({ 'point_as_seconds': itask.get_point_as_seconds(), }) if wall_clock(*ctx.func_args, **ctx.func_kwargs): itask.state.xtriggers[label] = True self.sat_xtrig[sig] = {} LOG.info('xtrigger satisfied: %s = %s', label, sig) continue # General case: asynchronous xtrigger function call. if sig in self.sat_xtrig: if not itask.state.xtriggers[label]: itask.state.xtriggers[label] = True res = {} for key, val in self.sat_xtrig[sig].items(): res["%s_%s" % (label, key)] = val if res: xtrigger_env = [{ 'environment': { key: val } } for key, val in res.items()] self.broadcast_mgr.put_broadcast([str(ctx.point)], [itask.tdef.name], xtrigger_env) continue if sig in self.active: # Already waiting on this result. continue now = time() if sig in self.t_next_call and now < self.t_next_call[sig]: # Too soon to call this one again. continue self.t_next_call[sig] = now + ctx.intvl # Queue to the process pool, and record as active. self.active.append(sig) self.proc_pool.put_command(ctx, self.callback)
def _get_xclock(self, itask: TaskProxy, sig_only: bool = False) ->\ Union[str, Tuple[str, str, SubFuncContext, bool]]: """(Internal helper method.) Args: itask (TaskProxy): TaskProxy sig_only (bool): whether to return the signature only or not Returns: Union[str, Tuple[str, str, SubFuncContext, bool]]: the signature of the function (if sigs_only True) or a tuple with label, signature, function context, and flag for satisfied. """ label, satisfied = itask.state.xclock ctx = deepcopy(self.clockx_map[label]) ctx.func_kwargs.update( { 'point_as_seconds': itask.get_point_as_seconds(), } ) sig = ctx.get_signature() if sig_only: return sig else: return label, sig, ctx, satisfied