class Response(DB.Model): __tablename__ = "responses" id = DB.Column(DB.Integer, primary_key=True) user_id = DB.Column(DB.Integer, DB.ForeignKey('users.id')) raw = DB.Column(DB.Text, nullable=False) happiness = DB.Column(DB.Integer) timestamp = DB.Column(DB.DateTime, nullable=False, default=datetime.utcnow)
class OutputFile(DB.Model): """ Class that represents an output file that the job produced. """ id = DB.Column(DB.Integer, primary_key=True) internal_path = DB.Column(DB.Text, nullable=False) public_url = DB.Column(DB.Text) job_id = DB.Column(DB.String(length=120), DB.ForeignKey('delayed_job.id'), nullable=False)
class CustomJobConfig(DB.Model): """ Class that represents a custom key-value instance for the configuration of jobs, that will be passed to the job's run params """ job_type = DB.Column(DB.String(length=60), DB.ForeignKey('default_job_config.job_type'), nullable=False, primary_key=True) key = DB.Column(DB.Text, primary_key=True) value = DB.Column(DB.Text)
class Busket(db.Model): __tablename__ = "Busket" __table_args__ = (UniqueConstraint('user_id', 'good_id', name='unique_user_good'), ) id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("User.id")) good_id = db.Column(db.Integer, db.ForeignKey("Good.id")) amount = db.Column(db.Integer) @property def commit(self) -> bool: db.session.add(self) try: db.session.commit() return True except IntegrityError: return False def update(self, amount: int): self.amount = amount db.session.commit() @staticmethod def delete(id: int) -> bool: try: db.session.delete(Busket.query.filter_by(id=id).first()) db.session.commit() return True except UnmappedInstanceError: return False @staticmethod def delete_all(user_id: int) -> bool: try: db.session.query(Busket).filter_by(user_id=user_id).delete() db.session.commit() return True except UnmappedInstanceError: return False
class Good(db.Model): __tablename__: str = "Good" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), unique=True) weight = db.Column(db.String(64)) description = db.Column(db.Text) measure = db.Column(db.String(64)) price = db.Column(db.Float) category_id = db.Column(db.Integer, db.ForeignKey("Category.id")) link = db.Column(db.Text) user_id = db.relationship( "Busket", backref="good", lazy="dynamic", foreign_keys="Busket.good_id", cascade="all, delete-orphan" ) def __repr__(self) -> str: return self.name def commit(self) -> bool: db.session.add(self) try: db.session.commit() return True except IntegrityError: return False def update(self, **kwargs): for key, value in kwargs.items(): if key != "category": self.__setattr__(key, value) db.session.commit() @staticmethod def first(**kwargs) -> Good: return Good.query.filter_by(**kwargs).first() @staticmethod def all() -> List[Good]: return Good.query.all() @staticmethod def delete(**kwargs) -> bool: try: db.session.delete(Good.query.filter_by(**kwargs).first()) db.session.commit() return True except UnmappedInstanceError: return False
class DelayedJob(DB.Model): """ Class that represents a delayed job in the database. """ id = DB.Column(DB.String(length=120), primary_key=True) type = DB.Column(DB.String(length=60), DB.ForeignKey('default_job_config.job_type'), nullable=False) status = DB.Column(DB.Enum(JobStatuses), default=JobStatuses.CREATED) status_log = DB.Column( DB.Text) # a comment about the status, for example 'Compressing file' progress = DB.Column(DB.Integer, default=0) created_at = DB.Column(DB.DateTime, default=datetime.datetime.utcnow) started_at = DB.Column(DB.DateTime) finished_at = DB.Column(DB.DateTime) run_dir_path = DB.Column(DB.Text) output_dir_path = DB.Column(DB.Text) raw_params = DB.Column(DB.Text) expires_at = DB.Column(DB.DateTime) api_initial_url = DB.Column(DB.Text) docker_image_url = DB.Column(DB.Text) timezone = DB.Column(DB.String(length=60), default=str(datetime.timezone.utc)) num_failures = DB.Column(DB.Integer, default=0) # How many times the job has failed. lsf_job_id = DB.Column(DB.Integer) lsf_host = DB.Column(DB.Text) requirements_parameters_string = DB.Column(DB.Text) status_description = DB.Column(DB.Text) run_environment = DB.Column(DB.String(length=60)) input_files = DB.relationship('InputFile', backref='delayed_job', lazy=True, cascade='all, delete-orphan') output_files = DB.relationship('OutputFile', backref='delayed_job', lazy=True, cascade='all, delete-orphan') def __repr__(self): return f'<DelayedJob ${self.id} ${self.type} ${self.status}>' def public_dict(self, server_base_url='http://0.0.0.0:5000'): """ Returns a dictionary representation of the object with all the fields that are safe to be public :param server_base_url: url to use as base for building the output files urls """ plain_properties = { key: str(getattr(self, key)) for key in [ 'id', 'type', 'status', 'status_log', 'progress', 'created_at', 'started_at', 'finished_at', 'raw_params', 'expires_at', 'api_initial_url', 'docker_image_url', 'timezone', 'num_failures', 'status_description' ] } input_files_urls = utils.get_input_files_dict(self.input_files, server_base_url) output_files_urls = utils.get_output_files_dict( self.output_files, server_base_url) return { **plain_properties, 'input_files_urls': input_files_urls, 'output_files_urls': output_files_urls } def update_run_status(self, new_value): """ Updates the run status of the job, if status switches to running, it calculates started_at. If the status switches to running, it calculates finished_at, and expires_at :param new_value: new run status """ old_value = self.status if str(old_value) != str(new_value): if new_value == str(JobStatuses.RUNNING): self.started_at = datetime.datetime.utcnow() elif new_value == str(JobStatuses.FINISHED): self.finished_at = datetime.datetime.utcnow() self.expires_at = datetime.datetime.utcnow( ) + datetime.timedelta(days=DAYS_TO_LIVE) self.status = new_value def get_executions_count(self): """ :return: how many times a job has been executed """ return len(self.executions)