示例#1
0
def _maybe_pubsub_notify_via_tq(result_summary, request):
    """Examines result_summary and enqueues a task to send PubSub message.

  Must be called within a transaction.

  Raises CommitError on errors (to abort the transaction).
  """
    assert ndb.in_transaction()
    assert isinstance(result_summary,
                      task_result.TaskResultSummary), result_summary
    assert isinstance(request, task_request.TaskRequest), request
    if (result_summary.state in task_result.State.STATES_NOT_RUNNING
            and request.pubsub_topic):
        task_id = task_pack.pack_result_summary_key(result_summary.key)
        ok = utils.enqueue_task(url='/internal/taskqueue/pubsub/%s' % task_id,
                                queue_name='pubsub',
                                transactional=True,
                                payload=utils.encode_to_json({
                                    'task_id':
                                    task_id,
                                    'topic':
                                    request.pubsub_topic,
                                    'auth_token':
                                    request.pubsub_auth_token,
                                    'userdata':
                                    request.pubsub_userdata,
                                }))
        if not ok:
            raise datastore_utils.CommitError(
                'Failed to enqueue task queue task')
示例#2
0
def notify_requests(es_cfg, requests, use_tq, is_callback, batch_mode=False):
    """Calls external scheduler to notify it of a task state.

  Arguments:
    - es_cfg: pools_config.ExternalSchedulerConfig for external scheduler to
        notify.
    - requests:
      A list of (task_request.TaskRequest,
                 task_result.TaskResultSummary or task_result.TaskRunResult)
      tuples.
    - use_tq: If true, make this call on a task queue (within the current
              datastore transaction).
    - is_callback: If true, indicates that this notification was in response
                   to a external-scheduler-requested callback. This is for
    - batch_mode: If true, the notifications will be sent in a batched mode
                  along with others, to reduce traffic to external scheduler.
                  Only valid when use_tq and global config's
                  enable_batch_es_notifications are true.

  Returns: Nothing.
  """
    logging.debug(
        'notify_requests(es_cfg=(%s,%s), requests=%s, use_tq=%s, '
        'is_callback=%s, batch_mode=%s)', es_cfg.address, es_cfg.id,
        [r.task_id for r, _ in requests], use_tq, is_callback, batch_mode)

    req = plugin_pb2.NotifyTasksRequest()
    req.is_callback = is_callback

    for request, result_summary in requests:
        item = req.notifications.add()
        # TODO(akeshet): This time should possibly come from the read time from
        # datastore, rather than the local server clock.
        item.time.FromDatetime(utils.utcnow())
        item.task.id = request.task_id
        item.task.tags.extend(request.tags)
        item.task.enqueued_time.FromDatetime(request.created_ts)
        for i in range(request.num_task_slices):
            s = request.task_slice(i)
            flat_dimensions = task_queues.bot_dimensions_to_flat(
                s.properties.dimensions)
            s_pb = item.task.slices.add()
            s_pb.dimensions.extend(flat_dimensions)

        res = swarming_pb2.TaskResult()
        result_summary.to_proto(res)
        item.task.state = res.state
        if result_summary.bot_id:
            # TODO(akeshet): We should only actually set this is state is running.
            item.task.bot_id = result_summary.bot_id

    req.scheduler_id = es_cfg.id

    if not use_tq:
        # Ignore return value, the response proto is empty.
        notify_request_now(es_cfg.address, req)
        return

    request_json = json_format.MessageToJson(req)
    # If enable_batch_es_notifications is true, the notifications will be sent in
    # a batched mode along with others, to reduce traffic to external scheduler.
    if batch_mode and config.settings().enable_batch_es_notifications:
        payload = {'es_host': es_cfg.address, 'request_json': request_json}
        req = taskqueue.Task(payload=json.dumps(payload), method='PULL')
        if not req.add(queue_name='es-notify-tasks-batch',
                       transactional=ndb.in_transaction()):
            raise datastore_utils.CommitError('Failed to enqueue task')
        stats = taskqueue.QueueStatistics.fetch('es-notify-kick')
        # Add a kicker task if there are fewer than 10 minutes worth.
        if stats.tasks < 600:
            job_enqueued = utils.enqueue_task(
                '/internal/taskqueue/important/external_scheduler/notify-kick',
                'es-notify-kick',
                transactional=ndb.in_transaction())
            if not job_enqueued:
                logging.info('Failed to add a notify-kick for request.')
        return

    enqueued = utils.enqueue_task(
        '/internal/taskqueue/important/external_scheduler/notify-tasks',
        'es-notify-tasks',
        params={
            'es_host': es_cfg.address,
            'request_json': request_json
        },
        transactional=ndb.in_transaction())
    if not enqueued:
        raise datastore_utils.CommitError('Failed to enqueue task')
示例#3
0
 def r(*_):
     raise datastore_utils.CommitError('Sorry!')