Skip to content

Commit a3f76ed

Browse files
author
Alan Christie
committed
docs: More doc and typo corrections
1 parent af44290 commit a3f76ed

File tree

4 files changed

+91
-45
lines changed

4 files changed

+91
-45
lines changed

workflow/decoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
The _main_ purpose of this module is to provide a 'validate_schema()' function
66
to check that a workflow definition (a dictionary) that is expected to comply with
77
the 'workflow-schema,yaml' schema. This function returns a string (an error) if there's
8-
a problem with the defintion.
8+
a problem with the definition.
99
1010
The decoder module also provides a number of additional functions based on the needs
1111
of the engine. As a developer you are 'encouraged' to place any logic that is expected

workflow/workflow_abc.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,55 @@
44
to the engine.
55
66
Before go any further it is important to understand that a Workflow 'Step' is realised
7-
by the execution of a Data Manager 'Job'. A 'Step' is simnply the definition of
8-
a Job's execution withion the context of a 'Workflow'. We also talk about 'Instances'.
7+
by the execution of a Data Manager 'Job'. A 'Step' is simply the definition of
8+
a Job's execution within the context of a 'Workflow'. We also talk about 'Instances'.
99
Instances are a Data Manger concept. They are an object (and database Table)
10-
represening the running state of a Job.
10+
representing the running state of a Job.
1111
1212
When steps 'Steps' are run the are represented by 'Jobs' that run as an 'Instance'.
1313
1414
To this end the workflow engine relies on a two broad external services, encapsulated
1515
by abstract class definitions we define here: -
1616
17-
- An 'Instance Laucncher' to facilitate the execution of Jobs
18-
- An API 'wrapper' providing access to an underling database that stores
19-
Workflows, RunningWorkflows, RunningWorkflowSteps, and Instances.
17+
- An 'Instance Launcher' to facilitate the execution of Jobs and dataclass objects
18+
encapsulating launch parameters and results
19+
- An API 'wrapper' providing access to an underling database that stores
20+
Workflows, RunningWorkflows, RunningWorkflowSteps, and Instances. API responses
21+
are Python dictionaries, emulating the payload of a REST response body.
22+
The engine _could_ use the DM REST API but we provide an _internal_ service
23+
to avoid issues with authentication and user tokens needed by the REST API.
2024
2125
Module philosophy
2226
-----------------
23-
The engine is responsible for orchestrating Step exection (executing Jobs) but does not
27+
The engine is responsible for orchestrating Step execution (executing Jobs) but does not
2428
contain the logic that is able to run them. This is because a) job execution
2529
(in Kubernetes) is a complex affair and b) the Data Manager already provides this
26-
logic. Instead the engine defines an ABC for an 'InstanceLaucnher' and the
30+
logic. Instead the engine defines an ABC for an 'InstanceLauncher' and the
2731
DM provides the implementation. The engine simply has to create a 'LaunchParameter'
28-
object describign the Job to be laucnhed (including variables etc.) and then
32+
object describing the Job to be launched (including variables etc.) and then
2933
relies on the Instance Launcher to effect the execution.
3034
3135
The engine also does not consist of any persistence capability and instead relies on the
3236
Data Manager's database to host suitable 'Workflow', 'RunningWorkflow',
3337
and 'RunningWorkflowStep' tables. The 'WorkflowAPIAdapter' defined here provides an
3438
interface that a concrete implementation uses to allow access to and modification
35-
of records withing these tables.
39+
of records within these tables.
3640
3741
The engine does not create or remove records directly, they are created either by the
38-
Data Manager via its API or the Instance laucnher when as it starts Jobs (Steps).
42+
Data Manager via its API or the Instance launcher when as it starts Jobs (Steps).
3943
The DM API creates a Workflow record when the user creates a Workflow.
40-
It also creates RunnignWorkflow records (while also validating them) when the
44+
It also creates RunningWorkflow records (while also validating them) when the
4145
user 'runs' a workflow. It also creates RunningWorkflowStep records to track the
42-
execution state of each step when the Instance lancher is called upon
46+
execution state of each step when the Instance launcher is called upon
4347
to start a Step.
4448
4549
The instance launcher is controlled by a complex set of 'parameters' (a
46-
'LaunchPrameters' dataclass object) that comprehensively descibe the Job -
47-
it's variables, and inputs and outputs. The instance launcher provies just one method:
48-
'launch()'. It takes a paramters object, and in return the yields a 'LaunchResult'
50+
'LaunchParameters' dataclass object) that comprehensively describe the Job -
51+
it's variables, and inputs and outputs. The instance launcher provides just one method:
52+
'launch()'. It takes a parameters object, and in return the yields a 'LaunchResult'
4953
dataclass object that contains the record IDs of the instance created, and the
5054
corresponding RunningWorkflowStep. The result also describes any launch error.
51-
If there is a laucnh error the tep can assume to have not started. if there is
55+
If there is a launch error the step can assume to have not started. if there is
5256
no error the step will (probably) start.
5357
"""
5458

workflow/workflow_engine.py

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,71 @@
11
"""The WorkflowEngine execution logic.
22
3-
Module philosophy
4-
-----------------
5-
The module implements the workflow execution logic, which is driven by
6-
Pod and Workflow protocol buffer messages received by its 'handle_message()' function.
7-
Messages are delivered by the message handler in the PBC Pod.
8-
There are no other publci methods in this class - it's _entry point_ is
9-
'handle_message()'.
10-
11-
Its role is to translate a pre-validated workflow definition into the ordered execution
12-
of step "Jobs" that manifest as Pod "Instances" that run in a project directory in the
3+
This module realises workflow definitions, turning a definition into a controlled sequence
4+
of Job executions. The Data Manager is responsible for storing and validating Workflows,
5+
and this module is responsible for running them and reporting their state back to the
136
DM.
147
15-
Workflow messages initiate (START) and terminate (STOP) workflows. Pod messages signal
16-
the end of individual workflow steps and carry the exit code of the executed Job.
17-
The engine used START messages to launch the first "step" in a workflow and the Pod
18-
messages to signal the success (or failure) of a prior step. A step's success is used,
19-
along with it's original workflow definition to determine the next action
20-
(run the next step or signal the end of the workflow).
21-
22-
Before a START message is transmitted the author (typically the Workflow Validator)
23-
will have created a RunningWorkflow record in the DM. The ID of this record is passed
24-
in the START message that is sent. The engine uses this ID to find the running workflow
25-
and the workflow. The engine creates RunningWorkflowStep records for each step that
26-
is executed, and it uses thew InstanceLauncher to launch the Job (a Pod) for each step.
8+
The engine is event-driven, responding to two types of message
9+
(in the form of Protocol Buffers) - Workflow messages and a Pod messages.
10+
These messages, sent from the DM Protocol Buffer Consumer (PBC), are delivered to the
11+
engine via its 'handle_message()' method. The engine must react to these messages
12+
appropriately by: -
13+
14+
- Starting the execution of a new Workflow
15+
(when it receives a Workflow 'START' message)
16+
- Stopping the execution of an exiting Workflow
17+
(when it receives a Workflow 'STOP' message)
18+
- Progressing an exiting running workflow to its next Step
19+
(when it receives a Pod message)
20+
21+
When running a workflow, once the engine determines the action (the Step to run)
22+
its most complex logic lies in the preparation of a set variables for the Step (Job).
23+
This logic is confined to '_prepare_step()', which returns a 'StepPreparationResponse'
24+
dataclass object. This object is used by the second key method in this module,
25+
'_launch()'. The launch methods used the prepared variables and launches (using
26+
a DM-provided 'InstanceLauncher' implementation) one or more Instances of a Step Job,
27+
providing each with an appropriate set of command variables.
28+
29+
Module philosophy
30+
-----------------
31+
The module's role is to translate a pre-validated workflow definition into the ordered
32+
execution of Step "Jobs" that manifest as Pod "Instances" running in a project directory
33+
under the control of the DM.
34+
35+
Workflow messages are used to initiate (START) and terminate (STOP) workflows.
36+
Pod messages signal the end of a previously launched step and carry the exit code
37+
of the executed Job.
38+
39+
The engine uses START messages to launch the first "step" in a workflow, while Pod
40+
messages signal the success (or failure) of a prior step. A step's success is used,
41+
along with it's original workflow definition to determine the next action - either
42+
the execution of a new step or the conclusion of the Workflow.
43+
44+
The engine does has no persistence and not create database records. Instead it relies
45+
on an API 'wrapper' to retrieve records and alter them.
46+
47+
Objects that provide API and InstanceLauncher implementations are made available
48+
to the engine when the DM creates it. passing them through the class initialiser.
49+
50+
The engine is designed not to retain any state persistence, it reacts to messages,
51+
reconstructing its state based on Workflow, RunningWorkflow, and RunningWorkflowStep
52+
records maintained by the DM. There's no real 'pattern' here - it's simply complex
53+
custom sequential logic that is executed from the context of 'handle_message()'
54+
that has to translate a workflow definition into running Job Instances.
55+
56+
If there is a pattern its closest approximation is probably a State pattern, closely
57+
related to a Finite State Machine with the function 'handle_message()' used to alter
58+
the engine's 'state'. The engine is in fact a complex running workflow 'state machine',
59+
hence the term 'Engine' (another term for machine) used in its class name.
60+
61+
Only one instance of the engine is created by the DM so it also essentially exists as a
62+
Singleton.
63+
64+
There are no sub-classes or other modules. Today all the state logic is captured
65+
in this single module. There is no need to introduce level of redirection that simply
66+
reduce the size of the file. There is a level of complexity that cannot be avoided -
67+
the need to understand how to move a workflow forward and how to prepare a set of
68+
variables for the next 'Step'.
2769
"""
2870

2971
import logging

workflow/workflow_validator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@
88
99
CREATE level validation simply checks that the workflow complies with the schema.
1010
Workflows are permitted in the DM that do not comply with the schema. This is
11-
becuase the DM is also used as a persistent store for Wwrfklows while editing - this
11+
because the DM is also used as a persistent store for Workflows while editing - this
1212
allows a user to 'save' a workflow that is incomplete with the intention of
1313
adjusting it at a later date prior to execution.
1414
1515
TAG level validation takes things a little further. In 'production' mode
16-
tagging is required prior to exeution. TAG level validatioin ensures that a workflow
17-
_should_ run if it is run - for examplke variable names are all correctly defined
16+
tagging is required prior to execution. TAG level validation ensures that a workflow
17+
_should_ run if it is run - for example variable names are all correctly defined
1818
and there are no duplicates.
1919
2020
RUN level extends TAG level validation by ensuring, for example, all the
2121
workflow variables are defined.
2222
2323
Validation is designed to allow a more relaxed engine implementation, negating the
2424
need for the engine to 'check', for example, that variables exist - the validator
25-
ensures they do so that the engine can concentrate on laucnhing steps rather than
26-
implementing swatchs of lines of logic to protect against mal-use.
25+
ensures they do so that the engine can concentrate on launching steps rather than
26+
implementing swathes of lines of logic to protect against improper use.
2727
2828
It is the Data Manager that is responsible for invoking the validator. It does this
2929
prior to allowing a user to run a workflow. When the engine receives a 'Workflow Start'

0 commit comments

Comments
 (0)