Support non task data environment, step 1 (#1745)
This commit is contained in:
parent
946f069fff
commit
ad0cf83cb6
|
@ -13,5 +13,8 @@ services:
|
|||
SPIFFWORKFLOW_BACKEND_ENV: "${SPIFFWORKFLOW_BACKEND_ENV:-local_development}"
|
||||
SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: ""
|
||||
XDG_CACHE_HOME: "/app/.cache"
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
volumes:
|
||||
- ./spiffworkflow-backend:/app
|
||||
|
|
|
@ -234,7 +234,7 @@ config_from_env("SPIFFWORKFLOW_BACKEND_DEBUG_TASK_CONSISTENCY", default=False)
|
|||
# we load the CustomBpmnScriptEngine at import time, where we do not have access to current_app,
|
||||
# so instead of using config, we use os.environ directly over there.
|
||||
# config_from_env("SPIFFWORKFLOW_BACKEND_USE_RESTRICTED_SCRIPT_ENGINE", default=True)
|
||||
|
||||
# config_from_env("SPIFFWORKFLOW_BACKEND_USE_NON_TASK_DATA_BASED_SCRIPT_ENGINE_ENVIRONMENT", default=False)
|
||||
|
||||
# adds the ProxyFix to Flask on http by processing the 'X-Forwarded-Proto' header
|
||||
# to make SpiffWorkflow aware that it should return https for the server urls etc rather than http.
|
||||
|
|
|
@ -162,7 +162,33 @@ class MissingProcessInfoError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class TaskDataBasedScriptEngineEnvironment(TaskDataEnvironment): # type: ignore
|
||||
class BaseCustomScriptEngineEnvironment(BasePythonScriptEngineEnvironment): # type: ignore
|
||||
def user_defined_state(self, external_context: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
return {}
|
||||
|
||||
def last_result(self) -> dict[str, Any]:
|
||||
return dict(self._last_result.items())
|
||||
|
||||
def clear_state(self) -> None:
|
||||
pass
|
||||
|
||||
def pop_state(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
return {}
|
||||
|
||||
def preserve_state(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def restore_state(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def finalize_result(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def revise_state_with_task_data(self, task: SpiffTask) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class TaskDataBasedScriptEngineEnvironment(BaseCustomScriptEngineEnvironment, TaskDataEnvironment): # type: ignore
|
||||
def __init__(self, environment_globals: dict[str, Any]):
|
||||
self._last_result: dict[str, Any] = {}
|
||||
self._non_user_defined_keys = {"__annotations__"}
|
||||
|
@ -181,29 +207,8 @@ class TaskDataBasedScriptEngineEnvironment(TaskDataEnvironment): # type: ignore
|
|||
self._last_result = context
|
||||
return True
|
||||
|
||||
def user_defined_state(self, external_context: dict[str, Any] | None = None) -> dict[str, Any]:
|
||||
return {}
|
||||
|
||||
def last_result(self) -> dict[str, Any]:
|
||||
return dict(self._last_result.items())
|
||||
|
||||
def clear_state(self) -> None:
|
||||
pass
|
||||
|
||||
def preserve_state(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def restore_state(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def finalize_result(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
pass
|
||||
|
||||
def revise_state_with_task_data(self, task: SpiffTask) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment): # type: ignore
|
||||
class NonTaskDataBasedScriptEngineEnvironment(BaseCustomScriptEngineEnvironment):
|
||||
PYTHON_ENVIRONMENT_STATE_KEY = "spiff__python_env_state"
|
||||
|
||||
def __init__(self, environment_globals: dict[str, Any]):
|
||||
|
@ -263,6 +268,10 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
|
|||
def clear_state(self) -> None:
|
||||
self.state = {}
|
||||
|
||||
def pop_state(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
key = self.PYTHON_ENVIRONMENT_STATE_KEY
|
||||
return data.pop(key, {}) # type: ignore
|
||||
|
||||
def preserve_state(self, bpmn_process_instance: BpmnWorkflow) -> None:
|
||||
key = self.PYTHON_ENVIRONMENT_STATE_KEY
|
||||
state = self.user_defined_state()
|
||||
|
@ -290,8 +299,13 @@ class NonTaskDataBasedScriptEngineEnvironment(BasePythonScriptEngineEnvironment)
|
|||
self.state[result_variable] = task.data.pop(result_variable)
|
||||
|
||||
|
||||
class CustomScriptEngineEnvironment(TaskDataBasedScriptEngineEnvironment):
|
||||
pass
|
||||
class CustomScriptEngineEnvironment:
|
||||
@staticmethod
|
||||
def create(environment_globals: dict[str, Any]) -> BaseCustomScriptEngineEnvironment:
|
||||
if os.environ.get("SPIFFWORKFLOW_BACKEND_USE_NON_TASK_DATA_BASED_SCRIPT_ENGINE_ENVIRONMENT") == "true":
|
||||
return NonTaskDataBasedScriptEngineEnvironment(environment_globals)
|
||||
|
||||
return TaskDataBasedScriptEngineEnvironment(environment_globals)
|
||||
|
||||
|
||||
class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
|
||||
|
@ -334,7 +348,7 @@ class CustomBpmnScriptEngine(PythonScriptEngine): # type: ignore
|
|||
default_globals.update(safe_globals)
|
||||
default_globals["__builtins__"]["__import__"] = _import
|
||||
|
||||
environment = CustomScriptEngineEnvironment(default_globals)
|
||||
environment = CustomScriptEngineEnvironment.create(default_globals)
|
||||
super().__init__(environment=environment)
|
||||
|
||||
def __get_augment_methods(self, task: SpiffTask | None) -> dict[str, Callable]:
|
||||
|
@ -564,9 +578,6 @@ class ProcessInstanceProcessor:
|
|||
script_engine_to_use.environment.restore_state(bpmn_process_instance)
|
||||
bpmn_process_instance.script_engine = script_engine_to_use
|
||||
|
||||
def preserve_script_engine_state(self) -> None:
|
||||
self._script_engine.environment.preserve_state(self.bpmn_process_instance)
|
||||
|
||||
@classmethod
|
||||
def _update_bpmn_definition_mappings(
|
||||
cls,
|
||||
|
@ -1519,10 +1530,18 @@ class ProcessInstanceProcessor:
|
|||
)
|
||||
)
|
||||
|
||||
def serialize(self) -> dict:
|
||||
def serialize(self, serialize_script_engine_state: bool = True) -> dict:
|
||||
self.check_task_data_size()
|
||||
self.preserve_script_engine_state()
|
||||
return self._serializer.to_dict(self.bpmn_process_instance) # type: ignore
|
||||
|
||||
if serialize_script_engine_state:
|
||||
self._script_engine.environment.preserve_state(self.bpmn_process_instance)
|
||||
|
||||
result = self._serializer.to_dict(self.bpmn_process_instance)
|
||||
|
||||
if not serialize_script_engine_state and "data" in result:
|
||||
self._script_engine.environment.pop_state(result["data"])
|
||||
|
||||
return result # type: ignore
|
||||
|
||||
def next_user_tasks(self) -> list[SpiffTask]:
|
||||
return self.bpmn_process_instance.get_tasks(state=TaskState.READY, manual=True) # type: ignore
|
||||
|
|
|
@ -149,7 +149,7 @@ class ProcessModelTestRunnerScriptEngine(PythonScriptEngine): # type: ignore
|
|||
default_globals.update(safe_globals)
|
||||
default_globals["__builtins__"]["__import__"] = _import
|
||||
|
||||
environment = CustomScriptEngineEnvironment(default_globals)
|
||||
environment = CustomScriptEngineEnvironment.create(default_globals)
|
||||
self.method_overrides = method_overrides
|
||||
super().__init__(environment=environment)
|
||||
|
||||
|
|
|
@ -104,8 +104,6 @@ class TaskModelError(Exception):
|
|||
|
||||
|
||||
class TaskService:
|
||||
PYTHON_ENVIRONMENT_STATE_KEY = "spiff__python_env_state"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
process_instance: ProcessInstanceModel,
|
||||
|
|
|
@ -111,7 +111,7 @@ class TestProcessInstanceMigrator(BaseTest):
|
|||
processor = ProcessInstanceProcessor(
|
||||
process_instance, include_task_data_for_completed_tasks=True, include_completed_subprocesses=True
|
||||
)
|
||||
bpmn_process_dict_version_4 = processor.serialize()
|
||||
bpmn_process_dict_version_4 = processor.serialize(serialize_script_engine_state=False)
|
||||
self.round_last_state_change(bpmn_process_dict_version_4)
|
||||
self.round_last_state_change(bpmn_process_dict_version_4_from_spiff)
|
||||
assert bpmn_process_dict_version_4 == bpmn_process_dict_version_4_from_spiff
|
||||
|
@ -208,7 +208,7 @@ class TestProcessInstanceMigrator(BaseTest):
|
|||
processor = ProcessInstanceProcessor(
|
||||
process_instance, include_task_data_for_completed_tasks=True, include_completed_subprocesses=True
|
||||
)
|
||||
bpmn_process_dict_version_3_after_import = processor.serialize()
|
||||
bpmn_process_dict_version_3_after_import = processor.serialize(serialize_script_engine_state=False)
|
||||
self.round_last_state_change(bpmn_process_dict_before_import)
|
||||
self.round_last_state_change(bpmn_process_dict_version_3_after_import)
|
||||
assert bpmn_process_dict_version_3_after_import == bpmn_process_dict_before_import
|
||||
|
|
Loading…
Reference in New Issue