<commit_before>from __future__ import absolute_import, print_function

from datetime import datetime
from flask import current_app
from sqlalchemy.sql import func

from changes.backends.base import UnrecoverableException
from changes.config import db, queue, statsreporter
from changes.constants import Status, Result
from changes.db.utils import try_create
from changes.jobs.signals import fire_signal
from changes.models import ItemStat, Job, JobPhase, JobPlan, JobStep, TestCase
from changes.queue.task import tracked_task
from changes.utils.agg import aggregate_status, safe_agg

# Maximum duration of failed job that we will consider retrying (in seconds)
MAX_DURATION_FOR_RETRY_SECS = 600


def aggregate_job_stat(job, name, func_=func.sum):
    value = db.session.query(
        func.coalesce(func_(ItemStat.value), 0),
    ).filter(
        ItemStat.item_id.in_(
            db.session.query(JobStep.id).filter(
                JobStep.job_id == job.id,
                JobStep.replacement_id.is_(None),
            )
        ),
        ItemStat.name == name,
    ).as_scalar()

    try_create(ItemStat, where={
        'item_id': job.id,
        'name': name,
        'value': value,
    })


def _should_retry_jobstep(step):
    return (step.result == Result.infra_failed and step.replacement_id is None
            and (not step.duration or step.duration / 1000 < MAX_DURATION_FOR_RETRY_SECS)
            # make sure this jobstep hasn't already been retried
            and JobStep.query.filter(JobStep.replacement_id == step.id).first() is None)


def _find_and_retry_jobsteps(phase, implementation):<commit_msg>Bump the time at which we'll retry a jobstep to 20 minutes<commit_after>from __future__ import absolute_import, print_function

from datetime import datetime
from flask import current_app
from sqlalchemy.sql import func

from changes.backends.base import UnrecoverableException
from changes.config import db, queue, statsreporter
from changes.constants import Status, Result
from changes.db.utils import try_create
from changes.jobs.signals import fire_signal
from changes.models import ItemStat, Job, JobPhase, JobPlan, JobStep, TestCase
from changes.queue.task import tracked_task
from changes.utils.agg import aggregate_status, safe_agg

# Maximum duration of failed job that we will consider retrying (in seconds)
# TODO(nate): make this a config
MAX_DURATION_FOR_RETRY_SECS = 900


def aggregate_job_stat(job, name, func_=func.sum):
    value = db.session.query(
        func.coalesce(func_(ItemStat.value), 0),
    ).filter(
        ItemStat.item_id.in_(
            db.session.query(JobStep.id).filter(
                JobStep.job_id == job.id,
                JobStep.replacement_id.is_(None),
            )
        ),
        ItemStat.name == name,
    ).as_scalar()

    try_create(ItemStat, where={
        'item_id': job.id,
        'name': name,
        'value': value,
    })


def _should_retry_jobstep(step):
    return (step.result == Result.infra_failed and step.replacement_id is None
            and (not step.duration or step.duration / 1000 < MAX_DURATION_FOR_RETRY_SECS)
            # make sure this jobstep hasn't already been retried
            and JobStep.query.filter(JobStep.replacement_id == step.id).first() is None)


def _find_and_retry_jobsteps(phase, implementation):
{'fraction_non_alphanumeric': 0.08328322309079976, 'fraction_numerical': 0.005411906193625977, 'mean_word_length': 3.4242021276595747, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7214314', 'n_tokens_mistral': 1014, 'n_tokens_neox': 975, 'n_words': 273}