4. Pretreatment for projects
Sometimes it is necessary to prepare a project before it is moved to the actual state. This could mean that the project data needs to be manipulated, that emails need to be sent or something completely different.
Create pretreatments
Section titled “Create pretreatments”Pretreatments are enabled by default but have no logic implemented, meaning every project simply passes through without
any actions taken. To add pretreatment logic, you have to overwrite the state’s method pretreatment():
class MyState(BaseState): ...
@classmethod def pretreatment(cls, project: Project) -> bool: ...This method receives the project the pretreatment has to be executed on. It returns a boolean, indicating if the pretreatment was successful or not.
This example shows a pretreatment that adds default resources for test projects in case that it did not request any:
from perseus.datamanager import Project, DatabaseManager, ResourceValue
class MyState(BaseClass): ...
@classmethod def pretreatment(cls, project: Project) -> bool: DEFAULT_RESOURCES_TEST_PROJECT = { "cluster_cpu_h": 25000, "cluster_gpu_h": 1000, "cluster_fpga": 500, } if project.project_type == "test": if len(project.requested_resources) == 0: db_manager = DatabaseManager() for ( resource_id, default_value, ) in DEFAULT_RESOURCES_TEST_PROJECT.items(): project.requested_resources.append( ResourceValue( resource_id=resource_id, value=default_value, start=project.start, end=project.end, ) ) oid = db_manager.add_item(project) if oid is None: return False
return TrueHandle pretreatment errors
Section titled “Handle pretreatment errors”Sometimes, you maybe want to include pretreatments which can fail, i.e. when you need to call an API to create a user.
In such a case, you can return False in the pretreatment() method. If that happens, the project will stay in the
pretreatment cycle and the pretreatment will be executed again on it.
If you wish to add a more complex error handling, you can overwrite the state’s method pretreatment_error():
class MyState(BaseState): ...
@classmethod def pretreatment_error(cls, project: Project): ...This method will be executed every time the pretreatment() method returns False. This means that, if the
pretreatment for a project fails every time, this method will be executed basically every minute.
If you wish to i.e. send emails to notify about the failed pretreatment and not want to be potentially bombarded with
emails, you can use the pretreatment_error() to also skip the pretreatment and move the project to the state:
from perseus.state_machine import Eventclass MyState(BaseState): ...
@classmethod def pretreatment_error(cls, project: Project): ... # your error handling MyState.trigger_internal_event(project, Event("PRETREATMENT"))Disable pretreatments
Section titled “Disable pretreatments”Pretreatments are enabled by default. This causes projects to always enter the pretreatment cycle, even if you did not specify any pretreatment logic.
If you want to disable pretreatments for a state completely, you need to overwrite the state’s method
get_internal_state_machine() like this:
...class MyState(BaseState): ...
@classmethod def get_internal_state_machine(cls, project: Project | None = None) -> StateMachine: return StateMachine(Path(("IN_STATE", None)))...This causes all projects to directly enter the state’s internal state IN_STATE, therefore skipping the internal state
PRETREATMENT.