Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/dispatch/data/source/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@
import logging

from schedule import every

from dispatch.data.source import service as source_service
from dispatch.database.core import SessionLocal
from dispatch.scheduler import scheduler
from dispatch.decorators import scheduled_project_task, timer
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
from dispatch.data.source import service as source_service
from dispatch.decorators import scheduled_project_task
from dispatch.scheduler import scheduler

log = logging.getLogger(__name__)


@scheduler.add(every(1).hour, name="sync-sources")
@timer
@scheduled_project_task
def sync_sources(db_session: SessionLocal, project: Project):
"""Syncs sources from external sources."""
Expand All @@ -26,17 +28,19 @@ def sync_sources(db_session: SessionLocal, project: Project):
)

if not plugin:
log.debug(f"No active plugins were found. PluginType: 'source' ProjectId: {project.id}")
log.debug(
f"Data sources not synced. No source plugin enabled. Project: {project.name}. Organization: {project.organization.name}"
)
return

log.debug(f"Getting source information via: {plugin.plugin.slug}")
log.debug(f"Getting data source information via plugin {plugin.plugin.slug}.")

sources = source_service.get_all(db_session=db_session, project_id=project.id)

for s in sources:
log.debug(f"Syncing Source. Source: {s}")
log.debug(f"Syncing data source {s}...")
if not s.external_id:
log.debug(f"Skipping source, no externalId Source: {s}")
log.debug(f"Skipping data source. No external id for source {s}.")
continue

data = plugin.instance.get(external_id=s.external_id)
Expand Down
7 changes: 5 additions & 2 deletions src/dispatch/document/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from sqlalchemy import func

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.nlp import build_phrase_matcher, build_term_vocab, extract_terms_from_text
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
Expand All @@ -18,6 +18,7 @@


@scheduler.add(every(1).day, name="sync-document-terms")
@timer
@scheduled_project_task
def sync_document_terms(db_session: SessionLocal, project: Project):
"""Performs term extraction from known documents."""
Expand All @@ -26,7 +27,9 @@ def sync_document_terms(db_session: SessionLocal, project: Project):
)

if not plugin:
log.warn(f"Document terms not synced. No storage plugin enabled in {project.name} project.")
log.warn(
f"Document terms not synced. No storage plugin enabled. Project: {project.name}. Organization: {project.organization.name}"
)
return

terms = term_service.get_all(db_session=db_session, project_id=project.id).all()
Expand Down
7 changes: 5 additions & 2 deletions src/dispatch/evergreen/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from typing import Any

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.document import service as document_service
from dispatch.messaging.strings import EVERGREEN_REMINDER
from dispatch.notification import service as notification_service
Expand All @@ -34,7 +34,9 @@ def create_evergreen_reminder(
db_session=db_session, plugin_type="email", project_id=project.id
)
if not plugin:
log.warning("Evergreen reminder not sent. No email plugin enabled.")
log.warning(
"Evergreen reminder not sent. No email plugin enabled. Project: {project.name}. Organization: {project.organization.name}"
)
return

items = []
Expand Down Expand Up @@ -91,6 +93,7 @@ def group_items_by_owner_and_type(items):


@scheduler.add(every().monday.at("18:00"), name="create-evergreen-reminders")
@timer
@scheduled_project_task
def create_evergreen_reminders(db_session: SessionLocal, project: Project):
"""Sends reminders for items that have evergreen enabled."""
Expand Down
6 changes: 3 additions & 3 deletions src/dispatch/feedback/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import logging

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.project.models import Project
from dispatch.scheduler import scheduler

from .messaging import send_incident_feedback_daily_report
from .service import get_all_last_x_hours_by_project_id


log = logging.getLogger(__name__)


Expand All @@ -22,7 +21,8 @@ def group_feedback_by_commander(feedback):
return grouped


@scheduler.add(every(1).day.at("17:00"), name="feedback-report-daily")
@scheduler.add(every(1).day.at("18:00"), name="feedback-report-daily")
@timer
@scheduled_project_task
def feedback_report_daily(db_session: SessionLocal, project: Project):
"""
Expand Down
5 changes: 4 additions & 1 deletion src/dispatch/incident/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from dispatch.conversation.enums import ConversationButtonActions
from dispatch.database.core import SessionLocal, resolve_attr
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.messaging.strings import (
INCIDENT,
INCIDENT_DAILY_REPORT,
Expand Down Expand Up @@ -37,6 +37,7 @@


@scheduler.add(every(1).hours, name="incident-auto-tagger")
@timer
@scheduled_project_task
def incident_auto_tagger(db_session: SessionLocal, project: Project):
"""Attempts to take existing tags and associate them with incidents."""
Expand Down Expand Up @@ -83,6 +84,7 @@ def incident_auto_tagger(db_session: SessionLocal, project: Project):


@scheduler.add(every(1).day.at("18:00"), name="incident-report-daily")
@timer
@scheduled_project_task
def incident_report_daily(db_session: SessionLocal, project: Project):
"""Creates and sends incident daily reports based on notifications."""
Expand Down Expand Up @@ -199,6 +201,7 @@ def incident_report_daily(db_session: SessionLocal, project: Project):


@scheduler.add(every(1).day.at("18:00"), name="incident-close-reminder")
@timer
@scheduled_project_task
def incident_close_reminder(db_session: SessionLocal, project: Project):
"""Sends a reminder to the incident commander to close out their incident."""
Expand Down
8 changes: 3 additions & 5 deletions src/dispatch/incident_cost/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from schedule import every

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.incident import service as incident_service
from dispatch.incident.enums import IncidentStatus
from dispatch.incident_cost.models import IncidentCostCreate
Expand All @@ -23,6 +23,7 @@


@scheduler.add(every(5).minutes, name="calculate-incidents-response-cost")
@timer
@scheduled_project_task
def calculate_incidents_response_cost(db_session: SessionLocal, project: Project):
"""Calculates and saves the response cost for all incidents."""
Expand All @@ -31,7 +32,7 @@ def calculate_incidents_response_cost(db_session: SessionLocal, project: Project
)
if response_cost_type is None:
log.warning(
f"A default cost type for response cost does not exist in the {project.name} project. Response costs won't be calculated."
f"A default cost type for response cost doesn't exist in the {project.name} project and organization {project.organization.name}. Response costs for incidents won't be calculated."
)
return

Expand Down Expand Up @@ -76,9 +77,6 @@ def calculate_incidents_response_cost(db_session: SessionLocal, project: Project
incident.incident_costs.append(incident_response_cost)
db_session.add(incident)
db_session.commit()

log.debug(f"{incident.name}'s response cost has been updated to ${amount:,.2f}")

except Exception as e:
# we shouldn't fail to update all incidents when one fails
log.exception(e)
3 changes: 2 additions & 1 deletion src/dispatch/monitor/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from schedule import every

from dispatch.database.core import SessionLocal, resolve_attr
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.incident import service as incident_service
from dispatch.incident.enums import IncidentStatus
from dispatch.messaging.strings import (
Expand Down Expand Up @@ -69,6 +69,7 @@ def run_monitors(db_session, project, monitor_plugin, incidents, notify: bool =


@scheduler.add(every(MONITOR_SYNC_INTERVAL).seconds, name="sync-active-stable-monitors")
@timer
@scheduled_project_task
def sync_active_stable_monitors(db_session: SessionLocal, project: Project):
"""Syncs incident monitors for active and stable incidents."""
Expand Down
3 changes: 2 additions & 1 deletion src/dispatch/report/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from schedule import every

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.incident import service as incident_service
from dispatch.incident.enums import IncidentStatus
from dispatch.project.models import Project
Expand All @@ -17,6 +17,7 @@


@scheduler.add(every(1).hours, name="incident-report-reminders")
@timer
@scheduled_project_task
def incident_report_reminders(db_session: SessionLocal, project: Project):
"""Sends report reminders to incident commanders for active incidents."""
Expand Down
12 changes: 7 additions & 5 deletions src/dispatch/signal/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@
import logging

from schedule import every

from dispatch.database.core import SessionLocal
from dispatch.scheduler import scheduler
from dispatch.project.models import Project
from dispatch.decorators import scheduled_project_task, timer
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
from dispatch.scheduler import scheduler
from dispatch.signal import flows as signal_flows
from dispatch.decorators import scheduled_project_task

log = logging.getLogger(__name__)


# TODO do we want per signal source flexibility?
@scheduler.add(every(1).minutes, name="signal-consume")
@timer
@scheduled_project_task
def consume_signals(db_session: SessionLocal, project: Project):
"""Consume signals from external sources."""
Expand All @@ -28,12 +30,12 @@ def consume_signals(db_session: SessionLocal, project: Project):

if not plugins:
log.debug(
f"No active plugins were found. PluginType: 'signal-consumer' ProjectId: {project.id}"
"No signals consumed. No signal-consumer plugins enabled. Project: {project.name}. Organization: {project.organization.name}"
)
return

for plugin in plugins:
log.debug(f"Consuming signals. Signal Consumer: {plugin.plugin.slug}")
log.debug(f"Consuming signals using signal-consumer plugin: {plugin.plugin.slug}")
signal_instances = plugin.instance.consume()
for signal_instance_data in signal_instances:
log.info(f"Attempting to process the following signal: {signal_instance_data}")
Expand Down
4 changes: 3 additions & 1 deletion src/dispatch/tag/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import NoReturn

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.incident import service as incident_service
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
Expand All @@ -23,6 +23,7 @@


@scheduler.add(every(1).hour, name="sync-tags")
@timer
@scheduled_project_task
def sync_tags(db_session: SessionLocal, project: Project) -> NoReturn:
"""Syncs tags from external sources."""
Expand All @@ -49,6 +50,7 @@ def sync_tags(db_session: SessionLocal, project: Project) -> NoReturn:


@scheduler.add(every(1).day, name="build-tag-models")
@timer
@scheduled_project_task
def build_tag_models(db_session: SessionLocal, project: Project) -> NoReturn:
"""Builds the incident tag recommendation models."""
Expand Down
6 changes: 4 additions & 2 deletions src/dispatch/task/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
from schedule import every

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.incident import service as incident_service
from dispatch.incident.enums import IncidentStatus
from dispatch.project.models import Project
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
from dispatch.scheduler import scheduler
from dispatch.task import service as task_service

Expand Down Expand Up @@ -72,6 +72,7 @@ def sync_tasks(db_session, task_plugin, incidents, lookback: int = 60, notify: b


@scheduler.add(every(1).day, name="sync-incident-tasks-daily")
@timer
@scheduled_project_task
def sync_incident_tasks_daily(db_session: SessionLocal, project: Project):
"""Syncs all incident tasks daily."""
Expand All @@ -91,6 +92,7 @@ def sync_incident_tasks_daily(db_session: SessionLocal, project: Project):


@scheduler.add(every(TASK_SYNC_INTERVAL).seconds, name="sync-active-stable-incident-tasks")
@timer
@scheduled_project_task
def sync_active_stable_incident_tasks(db_session: SessionLocal, project: Project):
"""Syncs active and stable incident tasks."""
Expand Down
7 changes: 5 additions & 2 deletions src/dispatch/term/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from schedule import every

from dispatch.database.core import SessionLocal
from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.plugin import service as plugin_service
from dispatch.project.models import Project
from dispatch.scheduler import scheduler
Expand All @@ -20,6 +20,7 @@


@scheduler.add(every(1).hour, name="sync-terms")
@timer
@scheduled_project_task
def sync_terms(db_session: SessionLocal, project: Project):
"""Syncs terms from external sources."""
Expand All @@ -28,7 +29,9 @@ def sync_terms(db_session: SessionLocal, project: Project):
)

if not term_plugin:
log.warning(f"Skipping syncing terms. No term plugin enabled. Project Id: {project.id}")
log.warning(
f"Skipping syncing terms. No term plugin enabled. Project: {project.name}. Organization: {project.organization.name}"
)
return

for t in term_plugin.instance.get():
Expand Down
3 changes: 2 additions & 1 deletion src/dispatch/workflow/scheduled.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from schedule import every
from sqlalchemy.orm import Session

from dispatch.decorators import scheduled_project_task
from dispatch.decorators import scheduled_project_task, timer
from dispatch.messaging.strings import (
INCIDENT_WORKFLOW_COMPLETE_NOTIFICATION,
INCIDENT_WORKFLOW_UPDATE_NOTIFICATION,
Expand Down Expand Up @@ -93,6 +93,7 @@ def sync_workflow(


@scheduler.add(every(WORKFLOW_SYNC_INTERVAL).seconds, name="sync-workflows")
@timer
@scheduled_project_task
def sync_workflows(db_session: Session, project: Project):
"""Syncs all workflows."""
Expand Down