From b148a89dc6410b7ec4b16917b18ba99e1fd73962 Mon Sep 17 00:00:00 2001 From: Herculino Trotta Date: Sun, 15 Dec 2024 10:06:31 -0300 Subject: [PATCH] feat(tasks): add error logging --- app/apps/common/tasks.py | 26 +++- app/apps/rules/tasks.py | 248 +++++++++++++++++---------------- app/apps/transactions/tasks.py | 14 +- 3 files changed, 162 insertions(+), 126 deletions(-) diff --git a/app/apps/common/tasks.py b/app/apps/common/tasks.py index 4cddd74..9e0d1aa 100644 --- a/app/apps/common/tasks.py +++ b/app/apps/common/tasks.py @@ -1,14 +1,26 @@ +import logging + from procrastinate import builtin_tasks from procrastinate.contrib.django import app +logger = logging.getLogger(__name__) + + @app.periodic(cron="0 4 * * *") @app.task(queueing_lock="remove_old_jobs", pass_context=True) async def remove_old_jobs(context, timestamp): - return await builtin_tasks.remove_old_jobs( - context, - max_hours=744, - remove_error=True, - remove_cancelled=True, - remove_aborted=True, - ) + try: + return await builtin_tasks.remove_old_jobs( + context, + max_hours=744, + remove_error=True, + remove_cancelled=True, + remove_aborted=True, + ) + except Exception as e: + logger.error( + "Error while executing 'remove_old_jobs' task", + exc_info=True, + ) + raise e diff --git a/app/apps/rules/tasks.py b/app/apps/rules/tasks.py index 906047c..d0f8381 100644 --- a/app/apps/rules/tasks.py +++ b/app/apps/rules/tasks.py @@ -1,4 +1,6 @@ -from cachalot.api import cachalot_disabled, invalidate +import logging + +from cachalot.api import cachalot_disabled from dateutil.relativedelta import relativedelta from procrastinate.contrib.django import app from simpleeval import EvalWithCompoundTypes @@ -13,137 +15,147 @@ from apps.transactions.models import ( ) +logger = logging.getLogger(__name__) + + @app.task def check_for_transaction_rules( instance_id: int, signal, ): - with cachalot_disabled(): + try: + with cachalot_disabled(): - instance = Transaction.objects.get(id=instance_id) + instance = Transaction.objects.get(id=instance_id) - context = { - "account_name": instance.account.name, - "account_id": instance.account.id, - "account_group_name": ( - instance.account.group.name if instance.account.group else None - ), - "account_group_id": ( - instance.account.group.id if instance.account.group else None - ), - "is_asset_account": instance.account.is_asset, - "is_archived_account": instance.account.is_archived, - "category_name": instance.category.name if instance.category else None, - "category_id": instance.category.id if instance.category else None, - "tag_names": [x.name for x in instance.tags.all()], - "tag_ids": [x.id for x in instance.tags.all()], - "entities_names": [x.name for x in instance.entities.all()], - "entities_ids": [x.id for x in instance.entities.all()], - "is_expense": instance.type == Transaction.Type.EXPENSE, - "is_income": instance.type == Transaction.Type.INCOME, - "is_paid": instance.is_paid, - "description": instance.description, - "amount": instance.amount, - "notes": instance.notes, - "date": instance.date, - "reference_date": instance.reference_date, - } + context = { + "account_name": instance.account.name, + "account_id": instance.account.id, + "account_group_name": ( + instance.account.group.name if instance.account.group else None + ), + "account_group_id": ( + instance.account.group.id if instance.account.group else None + ), + "is_asset_account": instance.account.is_asset, + "is_archived_account": instance.account.is_archived, + "category_name": instance.category.name if instance.category else None, + "category_id": instance.category.id if instance.category else None, + "tag_names": [x.name for x in instance.tags.all()], + "tag_ids": [x.id for x in instance.tags.all()], + "entities_names": [x.name for x in instance.entities.all()], + "entities_ids": [x.id for x in instance.entities.all()], + "is_expense": instance.type == Transaction.Type.EXPENSE, + "is_income": instance.type == Transaction.Type.INCOME, + "is_paid": instance.is_paid, + "description": instance.description, + "amount": instance.amount, + "notes": instance.notes, + "date": instance.date, + "reference_date": instance.reference_date, + } - functions = {"relativedelta": relativedelta} + functions = {"relativedelta": relativedelta} - simple = EvalWithCompoundTypes(names=context, functions=functions) + simple = EvalWithCompoundTypes(names=context, functions=functions) - if signal == "transaction_created": - rules = TransactionRule.objects.filter(active=True, on_create=True) - elif signal == "transaction_updated": - rules = TransactionRule.objects.filter(active=True, on_update=True) - else: - rules = TransactionRule.objects.filter(active=True) + if signal == "transaction_created": + rules = TransactionRule.objects.filter(active=True, on_create=True) + elif signal == "transaction_updated": + rules = TransactionRule.objects.filter(active=True, on_update=True) + else: + rules = TransactionRule.objects.filter(active=True) - for rule in rules: - if simple.eval(rule.trigger): - for action in rule.actions.all(): - if action.field in [ - TransactionRuleAction.Field.type, - TransactionRuleAction.Field.is_paid, - TransactionRuleAction.Field.date, - TransactionRuleAction.Field.reference_date, - TransactionRuleAction.Field.amount, - TransactionRuleAction.Field.description, - TransactionRuleAction.Field.notes, - ]: - setattr( - instance, - action.field, - simple.eval(action.value), - ) + for rule in rules: + if simple.eval(rule.trigger): + for action in rule.actions.all(): + if action.field in [ + TransactionRuleAction.Field.type, + TransactionRuleAction.Field.is_paid, + TransactionRuleAction.Field.date, + TransactionRuleAction.Field.reference_date, + TransactionRuleAction.Field.amount, + TransactionRuleAction.Field.description, + TransactionRuleAction.Field.notes, + ]: + setattr( + instance, + action.field, + simple.eval(action.value), + ) - elif action.field == TransactionRuleAction.Field.account: - value = simple.eval(action.value) - if isinstance(value, int): - account = Account.objects.get(id=value) - instance.account = account - elif isinstance(value, str): - account = Account.objects.filter(name=value).first() - instance.account = account - - elif action.field == TransactionRuleAction.Field.category: - value = simple.eval(action.value) - if isinstance(value, int): - category = TransactionCategory.objects.get(id=value) - instance.category = category - elif isinstance(value, str): - category = TransactionCategory.objects.get(name=value) - instance.category = category - - elif action.field == TransactionRuleAction.Field.tags: - value = simple.eval(action.value) - if isinstance(value, list): - # Clear existing tags - instance.tags.clear() - for tag_value in value: - if isinstance(tag_value, int): - tag = TransactionTag.objects.get(id=tag_value) - instance.tags.add(tag) - elif isinstance(tag_value, str): - tag = TransactionTag.objects.get(name=tag_value) - instance.tags.add(tag) - - elif isinstance(value, (int, str)): - # If a single value is provided, treat it as a single tag - instance.tags.clear() + elif action.field == TransactionRuleAction.Field.account: + value = simple.eval(action.value) if isinstance(value, int): - tag = TransactionTag.objects.get(id=value) - else: - tag = TransactionTag.objects.get(name=value) + account = Account.objects.get(id=value) + instance.account = account + elif isinstance(value, str): + account = Account.objects.filter(name=value).first() + instance.account = account - instance.tags.add(tag) - - elif action.field == TransactionRuleAction.Field.entities: - value = simple.eval(action.value) - if isinstance(value, list): - # Clear existing entities - instance.entities.clear() - for entity_value in value: - if isinstance(entity_value, int): - entity = TransactionEntity.objects.get( - id=entity_value - ) - instance.entities.add(entity) - elif isinstance(entity_value, str): - entity = TransactionEntity.objects.get( - name=entity_value - ) - instance.entities.add(entity) - - elif isinstance(value, (int, str)): - # If a single value is provided, treat it as a single entity - instance.entities.clear() + elif action.field == TransactionRuleAction.Field.category: + value = simple.eval(action.value) if isinstance(value, int): - entity = TransactionEntity.objects.get(id=value) - else: - entity = TransactionEntity.objects.get(name=value) + category = TransactionCategory.objects.get(id=value) + instance.category = category + elif isinstance(value, str): + category = TransactionCategory.objects.get(name=value) + instance.category = category - instance.entities.add(entity) + elif action.field == TransactionRuleAction.Field.tags: + value = simple.eval(action.value) + if isinstance(value, list): + # Clear existing tags + instance.tags.clear() + for tag_value in value: + if isinstance(tag_value, int): + tag = TransactionTag.objects.get(id=tag_value) + instance.tags.add(tag) + elif isinstance(tag_value, str): + tag = TransactionTag.objects.get(name=tag_value) + instance.tags.add(tag) - instance.save() + elif isinstance(value, (int, str)): + # If a single value is provided, treat it as a single tag + instance.tags.clear() + if isinstance(value, int): + tag = TransactionTag.objects.get(id=value) + else: + tag = TransactionTag.objects.get(name=value) + + instance.tags.add(tag) + + elif action.field == TransactionRuleAction.Field.entities: + value = simple.eval(action.value) + if isinstance(value, list): + # Clear existing entities + instance.entities.clear() + for entity_value in value: + if isinstance(entity_value, int): + entity = TransactionEntity.objects.get( + id=entity_value + ) + instance.entities.add(entity) + elif isinstance(entity_value, str): + entity = TransactionEntity.objects.get( + name=entity_value + ) + instance.entities.add(entity) + + elif isinstance(value, (int, str)): + # If a single value is provided, treat it as a single entity + instance.entities.clear() + if isinstance(value, int): + entity = TransactionEntity.objects.get(id=value) + else: + entity = TransactionEntity.objects.get(name=value) + + instance.entities.add(entity) + + instance.save() + except Exception as e: + logger.error( + "Error while executing 'check_for_transaction_rules' task", + exc_info=True, + ) + raise e diff --git a/app/apps/transactions/tasks.py b/app/apps/transactions/tasks.py index c12cec7..e0bfafc 100644 --- a/app/apps/transactions/tasks.py +++ b/app/apps/transactions/tasks.py @@ -1,9 +1,21 @@ +import logging + from procrastinate.contrib.django import app from apps.transactions.models import RecurringTransaction +logger = logging.getLogger(__name__) + + @app.periodic(cron="0 0 * * *") @app.task def generate_recurring_transactions(timestamp=None): - RecurringTransaction.generate_upcoming_transactions() + try: + RecurringTransaction.generate_upcoming_transactions() + except Exception as e: + logger.error( + "Error while executing 'generate_recurring_transactions' task", + exc_info=True, + ) + raise e