Remove multiple job failure tables in favor of one.
We don't know yet how useful the job failue tables will be, and maintaining multiple failure tables--one for every entity involved in CSP provisioning--is burdensome. This collapses them all into a single table that track the entity type (environment, portfolio, etc.) and the entity ID. That way we can construct queries when needed to find task results.
This commit is contained in:
57
atst/jobs.py
57
atst/jobs.py
@@ -3,12 +3,7 @@ import pendulum
|
||||
|
||||
from atst.database import db
|
||||
from atst.queue import celery
|
||||
from atst.models import (
|
||||
EnvironmentJobFailure,
|
||||
EnvironmentRoleJobFailure,
|
||||
EnvironmentRole,
|
||||
PortfolioJobFailure,
|
||||
)
|
||||
from atst.models import EnvironmentRole, JobFailure
|
||||
from atst.domain.csp.cloud import CloudProviderInterface, GeneralCSPException
|
||||
from atst.domain.environments import Environments
|
||||
from atst.domain.portfolios import Portfolios
|
||||
@@ -17,32 +12,26 @@ from atst.models.utils import claim_for_update
|
||||
from atst.utils.localization import translate
|
||||
|
||||
|
||||
class RecordPortfolioFailure(celery.Task):
|
||||
class RecordFailure(celery.Task):
|
||||
_ENTITIES = [
|
||||
"portfolio_id",
|
||||
"application_id",
|
||||
"environment_id",
|
||||
"environment_role_id",
|
||||
]
|
||||
|
||||
def _derive_entity_info(self, kwargs):
|
||||
matches = [e for e in self._ENTITIES if e in kwargs.keys()]
|
||||
if matches:
|
||||
match = matches[0]
|
||||
return {"entity": match.replace("_id", ""), "entity_id": kwargs[match]}
|
||||
else:
|
||||
return None
|
||||
|
||||
def on_failure(self, exc, task_id, args, kwargs, einfo):
|
||||
if "portfolio_id" in kwargs:
|
||||
failure = PortfolioJobFailure(
|
||||
portfolio_id=kwargs["portfolio_id"], task_id=task_id
|
||||
)
|
||||
db.session.add(failure)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
class RecordEnvironmentFailure(celery.Task):
|
||||
def on_failure(self, exc, task_id, args, kwargs, einfo):
|
||||
if "environment_id" in kwargs:
|
||||
failure = EnvironmentJobFailure(
|
||||
environment_id=kwargs["environment_id"], task_id=task_id
|
||||
)
|
||||
db.session.add(failure)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
class RecordEnvironmentRoleFailure(celery.Task):
|
||||
def on_failure(self, exc, task_id, args, kwargs, einfo):
|
||||
if "environment_role_id" in kwargs:
|
||||
failure = EnvironmentRoleJobFailure(
|
||||
environment_role_id=kwargs["environment_role_id"], task_id=task_id
|
||||
)
|
||||
info = self._derive_entity_info(kwargs)
|
||||
if info:
|
||||
failure = JobFailure(**info, task_id=task_id)
|
||||
db.session.add(failure)
|
||||
db.session.commit()
|
||||
|
||||
@@ -143,17 +132,17 @@ def do_provision_portfolio(csp: CloudProviderInterface, portfolio_id=None):
|
||||
fsm.trigger_next_transition()
|
||||
|
||||
|
||||
@celery.task(bind=True, base=RecordPortfolioFailure)
|
||||
@celery.task(bind=True, base=RecordFailure)
|
||||
def provision_portfolio(self, portfolio_id=None):
|
||||
do_work(do_provision_portfolio, self, app.csp.cloud, portfolio_id=portfolio_id)
|
||||
|
||||
|
||||
@celery.task(bind=True, base=RecordEnvironmentFailure)
|
||||
@celery.task(bind=True, base=RecordFailure)
|
||||
def create_environment(self, environment_id=None):
|
||||
do_work(do_create_environment, self, app.csp.cloud, environment_id=environment_id)
|
||||
|
||||
|
||||
@celery.task(bind=True, base=RecordEnvironmentFailure)
|
||||
@celery.task(bind=True, base=RecordFailure)
|
||||
def create_atat_admin_user(self, environment_id=None):
|
||||
do_work(
|
||||
do_create_atat_admin_user, self, app.csp.cloud, environment_id=environment_id
|
||||
|
||||
@@ -7,11 +7,7 @@ from .audit_event import AuditEvent
|
||||
from .clin import CLIN, JEDICLINType
|
||||
from .environment import Environment
|
||||
from .environment_role import EnvironmentRole, CSPRole
|
||||
from .job_failure import (
|
||||
EnvironmentJobFailure,
|
||||
EnvironmentRoleJobFailure,
|
||||
PortfolioJobFailure,
|
||||
)
|
||||
from .job_failure import JobFailure
|
||||
from .notification_recipient import NotificationRecipient
|
||||
from .permissions import Permissions
|
||||
from .permission_set import PermissionSet
|
||||
|
||||
@@ -30,8 +30,6 @@ class Environment(
|
||||
|
||||
claimed_until = Column(TIMESTAMP(timezone=True))
|
||||
|
||||
job_failures = relationship("EnvironmentJobFailure")
|
||||
|
||||
roles = relationship(
|
||||
"EnvironmentRole",
|
||||
back_populates="environment",
|
||||
|
||||
@@ -32,8 +32,6 @@ class EnvironmentRole(
|
||||
)
|
||||
application_role = relationship("ApplicationRole")
|
||||
|
||||
job_failures = relationship("EnvironmentRoleJobFailure")
|
||||
|
||||
csp_user_id = Column(String())
|
||||
claimed_until = Column(TIMESTAMP(timezone=True))
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from celery.result import AsyncResult
|
||||
from sqlalchemy import Column, String, Integer
|
||||
|
||||
from atst.models.base import Base
|
||||
import atst.models.mixins as mixins
|
||||
|
||||
|
||||
class EnvironmentJobFailure(Base, mixins.JobFailureMixin):
|
||||
__tablename__ = "environment_job_failures"
|
||||
class JobFailure(Base, mixins.TimestampsMixin):
|
||||
__tablename__ = "job_failures"
|
||||
|
||||
environment_id = Column(ForeignKey("environments.id"), nullable=False)
|
||||
id = Column(Integer(), primary_key=True)
|
||||
task_id = Column(String(), nullable=False)
|
||||
entity = Column(String(), nullable=False)
|
||||
entity_id = Column(String(), nullable=False)
|
||||
|
||||
@property
|
||||
def task(self):
|
||||
if not hasattr(self, "_task"):
|
||||
self._task = AsyncResult(self.task_id)
|
||||
|
||||
class EnvironmentRoleJobFailure(Base, mixins.JobFailureMixin):
|
||||
__tablename__ = "environment_role_job_failures"
|
||||
|
||||
environment_role_id = Column(ForeignKey("environment_roles.id"), nullable=False)
|
||||
|
||||
|
||||
class PortfolioJobFailure(Base, mixins.JobFailureMixin):
|
||||
__tablename__ = "portfolio_job_failures"
|
||||
|
||||
portfolio_id = Column(ForeignKey("portfolios.id"), nullable=False)
|
||||
return self._task
|
||||
|
||||
@@ -3,5 +3,4 @@ from .auditable import AuditableMixin
|
||||
from .permissions import PermissionsMixin
|
||||
from .deletable import DeletableMixin
|
||||
from .invites import InvitesMixin
|
||||
from .job_failure import JobFailureMixin
|
||||
from .state_machines import FSMMixin
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
from celery.result import AsyncResult
|
||||
from sqlalchemy import Column, String, Integer
|
||||
|
||||
|
||||
class JobFailureMixin(object):
|
||||
id = Column(Integer(), primary_key=True)
|
||||
task_id = Column(String(), nullable=False)
|
||||
|
||||
@property
|
||||
def task(self):
|
||||
if not hasattr(self, "_task"):
|
||||
self._task = AsyncResult(self.task_id)
|
||||
|
||||
return self._task
|
||||
Reference in New Issue
Block a user