<commit_before>from functools import wraps
from celery.log import get_task_logger
from celery.task import periodic_task
from datetime import datetime, timedelta
from django.core.cache import cache
from corehq.apps.receiverwrapper.models import RepeatRecord, FormRepeater
from couchdbkit.exceptions import ResourceConflict
from couchforms.models import XFormInstance
from dimagi.utils.parsing import json_format_datetime, ISO_MIN

logging = get_task_logger()

def run_only_once(fn):
    """If this function is running (in any thread) then don't run"""
    key = fn.__module__ + '.' + fn.__name__ + '_is_running'

    @wraps(fn)
    def _fn(*args, **kwargs):
        if not cache.get(key):
            cache.set(key, True, 10*60)
            try:
                fn(*args, **kwargs)
            finally:
                cache.set(key, False)
    return _fn

@periodic_task(run_every=timedelta(minutes=1))
@run_only_once
def check_repeaters():
    now = datetime.utcnow()

    repeat_records = RepeatRecord.all(due_before=now)

    for repeat_record in repeat_records:
        repeat_record.fire()
        try:
            repeat_record.save()
        except ResourceConflict:
            logging.error("ResourceConflict with repeat_record %s: %s" % (repeat_record.get_id, repeat_record.to_json()))<commit_msg>add exception logger in check_repeaters<commit_after>from functools import wraps
from celery.log import get_task_logger
from celery.task import periodic_task
from datetime import datetime, timedelta
from django.core.cache import cache
from corehq.apps.receiverwrapper.models import RepeatRecord, FormRepeater
from couchdbkit.exceptions import ResourceConflict
from couchforms.models import XFormInstance
from dimagi.utils.parsing import json_format_datetime, ISO_MIN
from dimagi.utils.logging import notify_exception

logging = get_task_logger()

def run_only_once(fn):
    """If this function is running (in any thread) then don't run"""
    key = fn.__module__ + '.' + fn.__name__ + '_is_running'

    @wraps(fn)
    def _fn(*args, **kwargs):
        if not cache.get(key):
            cache.set(key, True, 10*60)
            try:
                fn(*args, **kwargs)
            finally:
                cache.set(key, False)
    return _fn

@periodic_task(run_every=timedelta(minutes=1))
@run_only_once
def check_repeaters():
    now = datetime.utcnow()

    repeat_records = RepeatRecord.all(due_before=now)

    for repeat_record in repeat_records:
        try:
            repeat_record.fire()
        except AttributeError:
            logging.exception("Error firing repeat record %s" % repeat_record.get_id)
            raise

        try:
            repeat_record.save()
        except ResourceConflict:
            logging.error("ResourceConflict with repeat_record %s: %s" % (repeat_record.get_id, repeat_record.to_json()))
{'fraction_non_alphanumeric': 0.08863876187126275, 'fraction_numerical': 0.0035174111853675696, 'mean_word_length': 3.328767123287671, 'pattern_counts': {'":': 0, '<': 3, '<?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': '6870638', 'n_tokens_mistral': 858, 'n_tokens_neox': 820, 'n_words': 217}