Smooth parallelization of TI Processes with TM1py
Install TM1py:
pip install TM1py
Clone or download the RushTI Repository
-
Adjust
config.inito match your TM1 environment -
Create the
tasks.txtfile -
Execute the
RushTI.pyscript using either named arguments or positional arguments:
Use --help to see all available options:
python RushTI.py --help
| Argument | Short | Required | Default | Description |
|---|---|---|---|---|
--tasks |
-t |
Yes | - | Path to the tasks file |
--workers |
-w |
Yes | - | Maximum number of parallel workers |
--mode |
-m |
No | norm |
Execution mode: norm or opt |
--retries |
-r |
No | 0 |
Number of retries for failed processes |
--result |
-o |
No | rushti.csv |
Output file for execution results |
Examples:
python RushTI.py --tasks tasks.txt --workers 4
python RushTI.py -t tasks.txt -w 16 -m opt
python RushTI.py --tasks tasks.txt --workers 4 --mode norm --retries 3
python RushTI.py -t tasks.txt -w 8 -m opt -r 2 -o result.csvFor backwards compatibility, positional arguments are still supported:
python RushTI.py <tasks_file> <workers> [mode] [retries] [result_file]
Examples:
python RushTI.py tasks.txt 2 # Normal mode, 2 workers
python RushTI.py tasks.txt 16 opt # Optimized mode, 16 workers
python RushTI.py tasks.txt 4 norm 3 # Normal mode, 3 retries
python RushTI.py tasks.txt 8 opt 2 result.csv # Optimized mode, 2 retries, custom result fileParallelizes the TI process execution with n max workers while allowing for execution groups through the wait key word
python RushTI.py -t tasks.txt -w 16 -m norm -r 2 -o results.csv
# or using positional arguments:
python RushTI.py tasks.txt 16 norm 2 results.csvExample of tasks.txt in Normal run mode:
instance="tm1srv01" process="export.actuals" pMonth=Jan
instance="tm1srv01" process="export.actuals" pMonth=Feb
instance="tm1srv01" process="export.actuals" pMonth=Mar
instance="tm1srv01" process="export.actuals" pMonth=Apr
instance="tm1srv01" process="export.actuals" pMonth=May
instance="tm1srv01" process="export.actuals" pMonth=Jun
wait
instance="tm1srv02" process="import.actuals" pMonth=Jan
instance="tm1srv02" process="import.actuals" pMonth=Feb
instance="tm1srv02" process="import.actuals" pMonth=Mar
instance="tm1srv02" process="import.actuals" pMonth=Apr
instance="tm1srv02" process="import.actuals" pMonth=May
instance="tm1srv02" process="import.actuals" pMonth=Jun
wait
instance="tm1srv02" process="save.data.all"
Parallelizes the TI process execution with n max workers and allows to define individual dependencies between tasks.
Each task is assigned an id. On all tasks you can define predecessors that must have completed before it can run.
python RushTI.py -t tasks.txt -w 16 -m opt -r 3 -o results.csv
# or using positional arguments:
python RushTI.py tasks.txt 16 opt 3 results.csvExample of tasks.txt in Optimized Mode:
id="1" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=Jan
id="2" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=Feb
id="3" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=Mar
id="4" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=Apr
id="5" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=May
id="6" predecessors="" require_predecessor_success="" instance="tm1srv01" process="export.actuals" pMonth=Jun
id="7" predecessors="1" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=Jan
id="8" predecessors="2" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=Feb
id="9" predecessors="3" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=Mar
id="10" predecessors="4" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=Apr
id="11" predecessors="5" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=May
id="12" predecessors="6" require_predecessor_success="" instance="tm1srv02" process="load.actuals" pMonth=Jun
id="13" predecessors="7,8,9,10,11,12" require_predecessor_success="" instance="tm1srv02" process="save.data.all"
Please note that the same id can be assigned to multiple tasks.
Both OPT and NORM now support comments as well as empty lines
RushTI produces a result file with the below format. If no name is provided the file will be named rushti.csv.
Unlike the rushti.log file,
the result file is machine-readable and can be consumed with TI after the execution to gain infomation about the execution.
You can use the result file to raise an alert from TI when not all processes were successful.
| PID | Process Runs | Process Fails | Start | End | Runtime | Overall Success |
|---|---|---|---|---|---|---|
| 10332 | 8 | 0 | 2023-06-26 15:19:28.778457 | 2023-06-26 15:19:49.160629 | 0:00:20.382172 | True |
Instead of passing individual arguments per task, you can use the expandable assignment operator *=* (default is =)
to assign all elements from an MDX result to a parameter.
RushTI will then register one task per element in the MDX result set.
So this:
instance="tm1" process="export.actuals" pMonth*=*"{[Period].[Jan],[Period].[Feb],[Period].[Mar]}"
Is equivalent to this:
instance="tm1" process="export.actuals" pMonth=Jan
instance="tm1" process="export.actuals" pMonth=Feb
instance="tm1" process="export.actuals" pMonth=Mar
You can use expandable assignment on more than one parameter per line.
Expandable tasks can be used both in NORM and OPT execution mode.
Logging can be configured in logging_config.ini.
By default, RushTI maintains a small log file rushti.log with the most relevant info's about the execution
The log file is helpful for troubleshooting issues and understanding past executions
2023-08-09 14:05:26,506 - 3036 - INFO - RushTI starts. Parameters: ['C:\\RushTI\\RushTI.py', 'tasks.txt', '2'].
2023-08-09 14:05:30,626 - 3036 - INFO - Executing process: '}bedrock.server.wait' with parameters: {'pLogOutput': '1', 'pWaitSec': '6'} on instance: 'tm1srv01'
2023-08-09 14:05:36,633 - 3036 - INFO - Execution successful: Process '}bedrock.server.wait' with parameters: {'pLogOutput': '1', 'pWaitSec': '6'} with 0 retries on instance: tm1srv01. Elapsed time: 0:00:06.005861
...
2023-08-09 14:05:58,682 - 3036 - INFO - Execution successful: Process '}bedrock.server.wait' with parameters: {'pLogOutput': '1', 'pWaitSec': '4'} with 0 retries on instance: tm1srv01. Elapsed time: 0:00:04.008271
2023-08-09 14:06:00,692 - 3036 - INFO - Execution successful: Process '}bedrock.server.wait' with parameters: {'pLogOutput': '1', 'pWaitSec': '6'} with 0 retries on instance: tm1srv01. Elapsed time: 0:00:06.016828
2023-08-09 14:06:00,700 - 3036 - INFO - RushTI ends. 0 fails out of 8 executions. Elapsed time: 0:00:34.191408. Ran with parameters: ['C:\\RushTI\\RushTI.py', 'tasks.txt', '2']
If you don't have Python installed, you can use the pre-built Windows executable.
Download rushti.exe from the GitHub Releases page.
The executable requires these configuration files in the same directory as rushti.exe:
your-folder/
├── rushti.exe
├── config.ini # TM1 server connection settings (required)
├── logging_config.ini # Logging configuration (required)
└── tasks.txt # Your task file
- Copy
config.iniandlogging_config.inifrom this repository to your executable's folder - Edit
config.inito match your TM1 environment - Create your
tasks.txtfile
Using named arguments:
rushti.exe --tasks tasks.txt --workers 4 --mode norm
rushti.exe -t tasks.txt -w 4 -m normUsing positional arguments:
rushti.exe tasks.txt 4 normCheck the version or get help:
rushti.exe --version
rushti.exe --helpTo build the executable yourself:
-
Clone the repository and install dependencies
git clone https://github.com/cubewise-code/rushti.git cd rushti pip install -r requirements.txt pip install pyinstaller -
Build using the spec file
pyinstaller rushti.spec
-
Find the executable in the
dist/folder
TM1py - A python wrapper for the TM1 REST API
This project is licensed under the MIT License - see the LICENSE.md file for details
