iris-pex-embedded-python 3.1.5b6__py3-none-any.whl → 3.1.5b8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of iris-pex-embedded-python might be problematic. Click here for more details.

@@ -1,1405 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: iris_pex_embedded_python
3
- Version: 3.1.5b6
4
- Summary: Iris Interoperability based on Embedded Python
5
- Author-email: grongier <guillaume.rongier@intersystems.com>
6
- License: MIT License
7
-
8
- Copyright (c) 2019 InterSystems Developer Community
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
28
- Project-URL: homepage, https://github.com/grongierisc/interoperability-embedded-python
29
- Project-URL: documentation, https://github.com/grongierisc/interoperability-embedded-python/blob/master/README.md
30
- Project-URL: repository, https://github.com/grongierisc/interoperability-embedded-python
31
- Project-URL: issues, https://github.com/grongierisc/interoperability-embedded-python/issues
32
- Keywords: iris,intersystems,python,embedded
33
- Classifier: Development Status :: 5 - Production/Stable
34
- Classifier: Intended Audience :: Developers
35
- Classifier: License :: OSI Approved :: MIT License
36
- Classifier: Operating System :: OS Independent
37
- Classifier: Programming Language :: Python :: 3.6
38
- Classifier: Programming Language :: Python :: 3.7
39
- Classifier: Programming Language :: Python :: 3.8
40
- Classifier: Programming Language :: Python :: 3.9
41
- Classifier: Programming Language :: Python :: 3.10
42
- Classifier: Programming Language :: Python :: 3.11
43
- Classifier: Programming Language :: Python :: 3.12
44
- Classifier: Topic :: Utilities
45
- Description-Content-Type: text/markdown
46
- License-File: LICENSE
47
- Requires-Dist: dacite>=1.6.0
48
- Requires-Dist: xmltodict>=0.12.0
49
- Requires-Dist: iris-embedded-python-wrapper>=0.0.6
50
- Requires-Dist: setuptools>=40.8.0
51
-
52
- # 1. interoperability-embedded-python
53
-
54
- [![PyPI - Status](https://img.shields.io/pypi/status/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
55
- [![PyPI](https://img.shields.io/pypi/v/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
56
- [![PyPI - Downloads](https://img.shields.io/pypi/dm/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
57
- [![PyPI - License](https://img.shields.io/pypi/l/iris-pex-embedded-python)](https://pypi.org/project/iris-pex-embedded-python/)
58
- ![GitHub last commit](https://img.shields.io/github/last-commit/grongierisc/interoperability-embedded-python)
59
-
60
- This proof of concept aims to show how the **iris interoperability framework** can be use with **embedded python**.
61
-
62
- ## 1.1. Table of Contents
63
-
64
- - [1. interoperability-embedded-python](#1-interoperability-embedded-python)
65
- - [1.1. Table of Contents](#11-table-of-contents)
66
- - [1.2. Example](#12-example)
67
- - [1.3. Register a component](#13-register-a-component)
68
- - [2. Demo](#2-demo)
69
- - [3. Installation](#3-installation)
70
- - [3.1. With ZPM](#31-with-zpm)
71
- - [3.2. With PyPI](#32-with-pypi)
72
- - [3.2.1. Known issues](#321-known-issues)
73
- - [4. How to Run the Sample](#4-how-to-run-the-sample)
74
- - [4.1. Docker containers](#41-docker-containers)
75
- - [4.2. Management Portal and VSCode](#42-management-portal-and-vscode)
76
- - [4.3. Open the production](#43-open-the-production)
77
- - [5. What's inside the repository](#5-whats-inside-the-repository)
78
- - [5.1. Dockerfile](#51-dockerfile)
79
- - [5.2. .vscode/settings.json](#52-vscodesettingsjson)
80
- - [5.3. .vscode/launch.json](#53-vscodelaunchjson)
81
- - [5.4. .vscode/extensions.json](#54-vscodeextensionsjson)
82
- - [5.5. src folder](#55-src-folder)
83
- - [6. How it works](#6-how-it-works)
84
- - [6.1. The `__init__.py`file](#61-the-__init__pyfile)
85
- - [6.2. The `common` class](#62-the-common-class)
86
- - [6.3. The `business_host` class](#63-the-business_host-class)
87
- - [6.4. The `inbound_adapter` class](#64-the-inbound_adapter-class)
88
- - [6.5. The `outbound_adapter` class](#65-the-outbound_adapter-class)
89
- - [6.6. The `business_service` class](#66-the-business_service-class)
90
- - [6.7. The `business_process` class](#67-the-business_process-class)
91
- - [6.8. The `business_operation` class](#68-the-business_operation-class)
92
- - [6.8.1. The dispacth system](#681-the-dispacth-system)
93
- - [6.8.2. The methods](#682-the-methods)
94
- - [6.9. The `director` class](#69-the-director-class)
95
- - [6.10. The `objects`](#610-the-objects)
96
- - [6.11. The `messages`](#611-the-messages)
97
- - [6.12. How to regsiter a component](#612-how-to-regsiter-a-component)
98
- - [6.12.1. register\_component](#6121-register_component)
99
- - [6.12.2. register\_file](#6122-register_file)
100
- - [6.12.3. register\_folder](#6123-register_folder)
101
- - [6.12.4. migrate](#6124-migrate)
102
- - [6.12.4.1. setting.py file](#61241-settingpy-file)
103
- - [6.12.4.1.1. CLASSES section](#612411-classes-section)
104
- - [6.12.4.1.2. Productions section](#612412-productions-section)
105
- - [6.13. Direct use of IOP](#613-direct-use-of-iop)
106
- - [7. Command line](#7-command-line)
107
- - [7.1. help](#71-help)
108
- - [7.2. default](#72-default)
109
- - [7.3. lists](#73-lists)
110
- - [7.4. start](#74-start)
111
- - [7.5. kill](#75-kill)
112
- - [7.6. stop](#76-stop)
113
- - [7.7. restart](#77-restart)
114
- - [7.8. migrate](#78-migrate)
115
- - [7.9. export](#79-export)
116
- - [7.10. status](#710-status)
117
- - [7.11. version](#711-version)
118
- - [7.12. log](#712-log)
119
- - [8. Credits](#8-credits)
120
- - [9. Benchmarks](#9-benchmarks)
121
-
122
- ## 1.2. Example
123
-
124
- bo.py
125
- ```python
126
- from iop import BusinessOperation,Message
127
-
128
- class MyBusinessOperation(BusinessOperation):
129
-
130
- def on_init(self):
131
- #This method is called when the component is becoming active in the production
132
-
133
- self.log_info("[Python] ...MyBusinessOperation:on_init() is called")
134
-
135
- return
136
-
137
- def on_teardown(self):
138
- #This method is called when the component is becoming inactive in the production
139
-
140
- self.log_info("[Python] ...MyBusinessOperation:on_teardown() is called")
141
-
142
- return
143
-
144
- def on_message(self, message_input:MyRequest):
145
- # called from service/process/operation, message is of type MyRequest with property request_string
146
-
147
- self.log_info("[Python] ...MyBusinessOperation:on_message() is called with message:"+message_input.request_string)
148
-
149
- response = MyResponse("...MyBusinessOperation:on_message() echos")
150
-
151
- return response
152
-
153
- @dataclass
154
- class MyRequest(Message):
155
-
156
- request_string:str = None
157
-
158
- @dataclass
159
- class MyResponse(Message):
160
-
161
- my_string:str = None
162
-
163
- ```
164
-
165
- ## 1.3. Register a component
166
-
167
- To register a component, you need to create a `setting.py` file in the root of your project.<br>
168
-
169
- This file will be used to register your classes and productions.<br>
170
-
171
- e.g.:
172
- setting.py
173
- ```python
174
- from iop import Utils
175
-
176
- import bo
177
-
178
- CLASSES = {
179
- "Python.MyBusinessOperation": bo.MyBusinessOperation
180
- }
181
- ```
182
-
183
- Then you can use the `iop` command line to register your component.
184
-
185
- ```sh
186
- iop --migrate /path/to/your/project/setting.py
187
- ```
188
-
189
- # 2. Demo
190
-
191
- You can find a demo in the [src/python/demo](src/python/demo) folder.
192
-
193
- Other demos are aviailable in those repositories:
194
-
195
- - [training](https://github.com/grongierisc/formation-template-python)
196
- - [template](https://github.com/grongierisc/iris-python-interoperability-template)
197
- - [falsk](https://github.com/grongierisc/iris-python-flask-api-template)
198
- - [rest-to-dicom](https://github.com/grongierisc/RestToDicom)
199
-
200
- # 3. Installation
201
-
202
- ## 3.1. With ZPM
203
-
204
- ```objectscript
205
- zpm "install pex-embbeded-python"
206
- ```
207
-
208
- ## 3.2. With PyPI
209
-
210
- ```sh
211
- pip3 install iris-pex-embedded-python
212
- ```
213
-
214
- Import the ObjectScript classes, open an embedded python shell and run :
215
-
216
- ```python
217
- from iop import Utils
218
- Utils.setup()
219
- ```
220
-
221
- or use `iop` command line :
222
-
223
- ```sh
224
- iop --init
225
- ```
226
-
227
- ### 3.2.1. Known issues
228
-
229
- If the module is not updated, make sure to remove the old version :
230
-
231
- ```sh
232
- pip3 uninstall iris-pex-embedded-python
233
- ```
234
-
235
- or manually remove the `grongier` folder in `<iris_installation>/lib/python/`
236
-
237
- or force the installation with pip :
238
-
239
- ```sh
240
- pip3 install --upgrade iris-pex-embedded-python --target <iris_installation>/lib/python/
241
- ```
242
-
243
- # 4. How to Run the Sample
244
-
245
- ## 4.1. Docker containers
246
-
247
-
248
- In order to have access to the InterSystems images, we need to go to the following url: http://container.intersystems.com. After connecting with our InterSystems credentials, we will get our password to connect to the registry. In the docker VScode addon, in the image tab, by pressing connect registry and entering the same url as before (http://container.intersystems.com) as a generic registry, we will be asked to give our credentials. The login is the usual one but the password is the one we got from the website.
249
-
250
- From there, we should be able to build and compose our containers (with the `docker-compose.yml` and `Dockerfile` files given).
251
-
252
- ## 4.2. Management Portal and VSCode
253
-
254
- This repository is ready for [VS Code](https://code.visualstudio.com/).
255
-
256
- Open the locally-cloned `interoperability-embedeed-python` folder in VS Code.
257
-
258
- If prompted (bottom right corner), install the recommended extensions.
259
-
260
- **IMPORTANT**: When prompted, reopen the folder inside the container so you will be able to use the python components within it. The first time you do this it may take several minutes while the container is readied.
261
-
262
- By opening the folder remote you enable VS Code and any terminals you open within it to use the python components within the container. Configure these to use `/usr/irissys/bin/irispython`
263
-
264
- <img width="1614" alt="PythonInterpreter" src="https://user-images.githubusercontent.com/47849411/145864423-2de24aaa-036c-4beb-bda0-3a73fe15ccbd.png">
265
-
266
- ## 4.3. Open the production
267
- To open the production you can go to [production](http://localhost:52773/csp/irisapp/EnsPortal.ProductionConfig.zen?PRODUCTION=PEX.Production).<br>
268
- You can also click on the bottom on the `127.0.0.1:52773[IRISAPP]` button and select `Open Management Portal` then, click on [Interoperability] and [Configure] menus then click [productions] and [Go].
269
-
270
- The production already has some code sample.
271
-
272
- Here we can see the production and our pure python services and operations:
273
- <img width="1177" alt="interop-screenshot" src="https://user-images.githubusercontent.com/47849411/131305197-d19511fd-6e05-4aec-a525-c88e6ebd0971.png">
274
-
275
- <br>
276
-
277
- New json trace for python native messages :
278
- <img width="910" alt="json-message-trace" src="https://user-images.githubusercontent.com/47849411/131305211-b8beb2c0-438d-4afc-a6d2-f94d854373ae.png">
279
-
280
- # 5. What's inside the repository
281
-
282
- ## 5.1. Dockerfile
283
-
284
- A dockerfile which install some python dependancies (pip, venv) and sudo in the container for conviencies.
285
- Then it create the dev directory and copy in it this git repository.
286
-
287
- It starts IRIS and activates **%Service_CallIn** for **Python Shell**.
288
- Use the related docker-compose.yml to easily setup additional parametes like port number and where you map keys and host folders.
289
-
290
- This dockerfile ends with the installation of requirements for python modules.
291
-
292
- Use .env/ file to adjust the dockerfile being used in docker-compose.
293
-
294
- ## 5.2. .vscode/settings.json
295
-
296
- Settings file to let you immedietly code in VSCode with [VSCode ObjectScript plugin](https://marketplace.visualstudio.com/items?itemName=daimor.vscode-objectscript)
297
-
298
- ## 5.3. .vscode/launch.json
299
- Config file if you want to debug with VSCode ObjectScript
300
-
301
- [Read about all the files in this article](https://community.intersystems.com/post/dockerfile-and-friends-or-how-run-and-collaborate-objectscript-projects-intersystems-iris)
302
-
303
- ## 5.4. .vscode/extensions.json
304
- Recommendation file to add extensions if you want to run with VSCode in the container.
305
-
306
- [More information here](https://code.visualstudio.com/docs/remote/containers)
307
-
308
- This is very useful to work with embedded python.
309
-
310
- ## 5.5. src folder
311
-
312
- ```
313
- src
314
- ├── Grongier
315
- │ └── PEX // ObjectScript classes that wrap python code
316
- │ ├── BusinessOperation.cls
317
- │ ├── BusinessProcess.cls
318
- │ ├── BusinessService.cls
319
- │ ├── Common.cls
320
- │ ├── Director.cls
321
- │ ├── InboundAdapter.cls
322
- │ ├── Message.cls
323
- │ ├── OutboundAdapter.cls
324
- │ ├── Python.cls
325
- │ ├── Test.cls
326
- │ └── _utils.cls
327
- ├── PEX // Some example of wrapped classes
328
- │ └── Production.cls
329
- └── python
330
- ├── demo // Actual python code to run this demo
331
- | `-- reddit
332
- | |-- adapter.py
333
- | |-- bo.py
334
- | |-- bp.py
335
- | |-- bs.py
336
- | |-- message.py
337
- | `-- obj.py
338
- ├── dist // Wheel used to implement python interoperability components
339
- │ └── grongier_pex-1.2.4-py3-none-any.whl
340
- ├── grongier
341
- │ └── pex // Helper classes to implement interoperability components
342
- │ ├── _business_host.py
343
- │ ├── _business_operation.py
344
- │ ├── _business_process.py
345
- │ ├── _business_service.py
346
- │ ├── _common.py
347
- │ ├── _director.py
348
- │ ├── _inbound_adapter.py
349
- │ ├── _message.py
350
- │ ├── _outbound_adapter.py
351
- │ ├── __init__.py
352
- │ └── _utils.py
353
- └── setup.py // setup to build the wheel
354
- ```
355
- # 6. How it works
356
-
357
- ## 6.1. The `__init__.py`file
358
- This file will allow us to create the classes to import in the code.<br>
359
- It gets from the multiple files seen earlier the classes and make them into callable classes.
360
- That way, when you wish to create a business operation, for example, you can just do:
361
- ```python
362
- from iop import BusinessOperation
363
- ```
364
-
365
- ## 6.2. The `common` class
366
- The common class shouldn't be called by the user, it defines almost all the other classes.<br>
367
- This class defines:
368
-
369
- `on_init`: The on_init() method is called when the component is started.<br> Use the on_init() method to initialize any structures needed by the component.
370
-
371
- `on_tear_down`: Called before the component is terminated.<br> Use it to free any structures.
372
-
373
- `on_connected`: The on_connected() method is called when the component is connected or reconnected after being disconnected.<br>Use the on_connected() method to initialize any structures needed by the component.
374
-
375
- `log_info`: Write a log entry of type "info". :log entries can be viewed in the management portal.
376
-
377
- `log_alert`: Write a log entry of type "alert". :log entries can be viewed in the management portal.
378
-
379
- `log_warning`: Write a log entry of type "warning". :log entries can be viewed in the management portal.
380
-
381
- `log_error`: Write a log entry of type "error". :log entries can be viewed in the management portal.
382
-
383
- ## 6.3. The `business_host` class
384
- The business host class shouldn't be called by the user, it is the base class for all the business classes.<br>
385
- This class defines:
386
-
387
- `send_request_sync`: Send the specified message to the target business process or business operation synchronously.
388
- **Parameters**:<br>
389
- - **target**: a string that specifies the name of the business process or operation to receive the request. <br>
390
- The target is the name of the component as specified in the Item Name property in the production definition, not the class name of the component.
391
- - **request**: specifies the message to send to the target. The request is either an instance of a class that is a subclass of Message class or of IRISObject class.<br>
392
- If the target is a build-in ObjectScript component, you should use the IRISObject class. The IRISObject class enables the PEX framework to convert the message to a class supported by the target.
393
- - **timeout**: an optional integer that specifies the number of seconds to wait before treating the send request as a failure. The default value is -1, which means wait forever.<br>
394
- description: an optional string parameter that sets a description property in the message header. The default is None.
395
-
396
- **Returns**:
397
- the response object from target.
398
-
399
- **Raises**:
400
- TypeError: if request is not of type Message or IRISObject.
401
-
402
- <br><br>
403
-
404
- `send_request_async`: Send the specified message to the target business process or business operation asynchronously.
405
- **Parameters**:<br>
406
- - **target**: a string that specifies the name of the business process or operation to receive the request. <br>
407
- The target is the name of the component as specified in the Item Name property in the production definition, not the class name of the component.
408
- - **request**: specifies the message to send to the target. The request is an instance of IRISObject or of a subclass of Message.<br>
409
- If the target is a built-in ObjectScript component, you should use the IRISObject class. The IRISObject class enables the PEX framework to convert the message to a class supported by the target.
410
- - **description**: an optional string parameter that sets a description property in the message header. The default is None.
411
-
412
- **Raises**:
413
- TypeError: if request is not of type Message or IRISObject.
414
-
415
- <br><br>
416
-
417
- `get_adapter_type`: Name of the registred Adapter.
418
-
419
-
420
- ## 6.4. The `inbound_adapter` class
421
- Inbound Adapter in Python are subclass from iop.InboundAdapter in Python, that inherit from all the functions of the [common class](#72-the-common-class).<br>
422
- This class is responsible for receiving the data from the external system, validating the data, and sending it to the business service by calling the BusinessHost process_input method.
423
- This class defines:
424
-
425
- `on_task`: Called by the production framework at intervals determined by the business service CallInterval property.<br>
426
- The message can have any structure agreed upon by the inbound adapter and the business service.
427
-
428
- Example of an inbound adapter ( situated in the src/python/demo/reddit/adapter.py file ):
429
- ```python
430
- from iop import InboundAdapter
431
- import requests
432
- import iris
433
- import json
434
-
435
- class RedditInboundAdapter(InboundAdapter):
436
- """
437
- This adapter use requests to fetch self.limit posts as data from the reddit
438
- API before calling process_input for each post.
439
- """
440
- def on_init(self):
441
-
442
- if not hasattr(self,'feed'):
443
- self.feed = "/new/"
444
-
445
- if self.limit is None:
446
- raise TypeError('no Limit field')
447
-
448
- self.last_post_name = ""
449
-
450
- return 1
451
-
452
- def on_task(self):
453
- self.log_info(f"LIMIT:{self.limit}")
454
- if self.feed == "" :
455
- return 1
456
-
457
- tSC = 1
458
- # HTTP Request
459
- try:
460
- server = "https://www.reddit.com"
461
- request_string = self.feed+".json?before="+self.last_post_name+"&limit="+self.limit
462
- self.log_info(server+request_string)
463
- response = requests.get(server+request_string)
464
- response.raise_for_status()
465
-
466
- data = response.json()
467
- updateLast = 0
468
-
469
- for key, value in enumerate(data['data']['children']):
470
- if value['data']['selftext']=="":
471
- continue
472
- post = iris.cls('dc.Reddit.Post')._New()
473
- post._JSONImport(json.dumps(value['data']))
474
- post.OriginalJSON = json.dumps(value)
475
- if not updateLast:
476
- self.LastPostName = value['data']['name']
477
- updateLast = 1
478
- response = self.BusinessHost.ProcessInput(post)
479
- except requests.exceptions.HTTPError as err:
480
- if err.response.status_code == 429:
481
- self.log_warning(err.__str__())
482
- else:
483
- raise err
484
- except Exception as err:
485
- self.log_error(err.__str__())
486
- raise err
487
-
488
- return tSC
489
- ```
490
-
491
- ## 6.5. The `outbound_adapter` class
492
- Outbound Adapter in Python are subclass from iop.OutboundAdapter in Python, that inherit from all the functions of the [common class](#72-the-common-class).<br>
493
- This class is responsible for sending the data to the external system.
494
-
495
- The Outbound Adapter gives the Operation the possibility to have a heartbeat notion.
496
- To activate this option, the CallInterval parameter of the adapter must be strictly greater than 0.
497
-
498
- <img width="301" alt="image" src="https://user-images.githubusercontent.com/47849411/178230243-39806602-a63d-4a89-9563-fcf6836d0515.png">
499
-
500
- Example of an outbound adapter ( situated in the src/python/demo/reddit/adapter.py file ):
501
-
502
- ```python
503
- class TestHeartBeat(OutboundAdapter):
504
-
505
- def on_keepalive(self):
506
- self.log_info('beep')
507
-
508
- def on_task(self):
509
- self.log_info('on_task')
510
- ```
511
-
512
- ## 6.6. The `business_service` class
513
- This class is responsible for receiving the data from external system and sending it to business processes or business operations in the production.<br>
514
- The business service can use an adapter to access the external system, which is specified overriding the get_adapter_type method.<br>
515
- There are three ways of implementing a business service:<br>
516
- - Polling business service with an adapter - The production framework at regular intervals calls the adapter’s OnTask() method,
517
- which sends the incoming data to the the business service ProcessInput() method, which, in turn calls the OnProcessInput method with your code.
518
-
519
- - Polling business service that uses the default adapter - In this case, the framework calls the default adapter's OnTask method with no data.
520
- The OnProcessInput() method then performs the role of the adapter and is responsible for accessing the external system and receiving the data.
521
-
522
- - Nonpolling business service - The production framework does not initiate the business service. Instead custom code in either a long-running process
523
- or one that is started at regular intervals initiates the business service by calling the Director.CreateBusinessService() method.
524
-
525
- Business service in Python are subclass from iop.BusinessService in Python, that inherit from all the functions of the [business host](#73-the-business_host-class).<br>
526
- This class defines:
527
-
528
- `on_process_input`: Receives the message from the inbond adapter via the PRocessInput method and is responsible for forwarding it to target business processes or operations.<br>
529
- If the business service does not specify an adapter, then the default adapter calls this method with no message and the business service is responsible for receiving the data from the external system and validating it.
530
- **Parameters**:<br>
531
- - **message_input**: an instance of IRISObject or subclass of Message containing the data that the inbound adapter passes in.<br>
532
- The message can have any structure agreed upon by the inbound adapter and the business service.
533
-
534
- <br><br>
535
-
536
- Example of a business service ( situated in the src/python/demo/reddit/bs.py file ):
537
- ```python
538
- from iop import BusinessService
539
-
540
- import iris
541
-
542
- from message import PostMessage
543
- from obj import PostClass
544
-
545
- class RedditServiceWithPexAdapter(BusinessService):
546
- """
547
- This service use our python Python.RedditInboundAdapter to receive post
548
- from reddit and call the FilterPostRoutingRule process.
549
- """
550
- def get_adapter_type():
551
- """
552
- Name of the registred Adapter
553
- """
554
- return "Python.RedditInboundAdapter"
555
-
556
- def on_process_input(self, message_input):
557
- msg = iris.cls("dc.Demo.PostMessage")._New()
558
- msg.Post = message_input
559
- return self.send_request_sync(self.target,msg)
560
-
561
- def on_init(self):
562
-
563
- if not hasattr(self,'target'):
564
- self.target = "Python.FilterPostRoutingRule"
565
-
566
- return
567
- ```
568
-
569
-
570
- ## 6.7. The `business_process` class
571
- Typically contains most of the logic in a production.<br>
572
- A business process can receive messages from a business service, another business process, or a business operation.<br>
573
- It can modify the message, convert it to a different format, or route it based on the message contents.<br>
574
- The business process can route a message to a business operation or another business process.<br>
575
- Business processes in Python are subclass from iop.BusinessProcess in Python, that inherit from all the functions of the [business host](#73-the-business_host-class).<br>
576
- This class defines:
577
-
578
- `on_request`: Handles requests sent to the business process. A production calls this method whenever an initial request for a specific business process arrives on the appropriate queue and is assigned a job in which to execute.<br>
579
- **Parameters**:<br>
580
- - **request**: An instance of IRISObject or subclass of Message that contains the request message sent to the business process.
581
-
582
- **Returns**:
583
- An instance of IRISObject or subclass of Message that contains the response message that this business process can return
584
- to the production component that sent the initial message.
585
-
586
- <br><br>
587
-
588
- `on_response`: Handles responses sent to the business process in response to messages that it sent to the target.<br>
589
- A production calls this method whenever a response for a specific business process arrives on the appropriate queue and is assigned a job in which to execute.<br>
590
- Typically this is a response to an asynchronous request made by the business process where the responseRequired parameter has a true value.<br>
591
- **Parameters**:<br>
592
- - **request**: An instance of IRISObject or subclass of Message that contains the initial request message sent to the business process.
593
- - **response**: An instance of IRISObject or subclass of Message that contains the response message that this business process can return to the production component that sent the initial message.
594
- - **callRequest**: An instance of IRISObject or subclass of Message that contains the request that the business process sent to its target.
595
- - **callResponse**: An instance of IRISObject or subclass of Message that contains the incoming response.
596
- - **completionKey**: A string that contains the completionKey specified in the completionKey parameter of the outgoing SendAsync() method.
597
-
598
- **Returns**:
599
- An instance of IRISObject or subclass of Message that contains the response message that this business process can return
600
- to the production component that sent the initial message.
601
-
602
- <br><br>
603
-
604
- `on_complete`: Called after the business process has received and handled all responses to requests it has sent to targets.<br>
605
- **Parameters**:
606
- - **request**: An instance of IRISObject or subclass of Message that contains the initial request message sent to the business process.<br>
607
- - **response**: An instance of IRISObject or subclass of Message that contains the response message that this business process can return to the production component that sent the initial message.
608
-
609
- **Returns**:
610
- An instance of IRISObject or subclass of Message that contains the response message that this business process can return to the production component that sent the initial message.
611
-
612
- <br><br>
613
-
614
- Example of a business process ( situated in the src/python/demo/reddit/bp.py file ):
615
- ```python
616
- from iop import BusinessProcess
617
-
618
- from message import PostMessage
619
- from obj import PostClass
620
-
621
- class FilterPostRoutingRule(BusinessProcess):
622
- """
623
- This process receive a PostMessage containing a reddit post.
624
- It then understand if the post is about a dog or a cat or nothing and
625
- fill the right infomation inside the PostMessage before sending it to
626
- the FileOperation operation.
627
- """
628
- def on_init(self):
629
-
630
- if not hasattr(self,'target'):
631
- self.target = "Python.FileOperation"
632
-
633
- return
634
-
635
- def on_request(self, request):
636
-
637
- if 'dog'.upper() in request.post.selftext.upper():
638
- request.to_email_address = 'dog@company.com'
639
- request.found = 'Dog'
640
- if 'cat'.upper() in request.post.selftext.upper():
641
- request.to_email_address = 'cat@company.com'
642
- request.found = 'Cat'
643
-
644
- if request.found is not None:
645
- return self.send_request_sync(self.target,request)
646
- else:
647
- return
648
- ```
649
-
650
- ## 6.8. The `business_operation` class
651
- This class is responsible for sending the data to an external system or a local system such as an iris database.<br>
652
- The business operation can optionally use an adapter to handle the outgoing message which is specified overriding the get_adapter_type method.<br>
653
- If the business operation has an adapter, it uses the adapter to send the message to the external system.<br>
654
- The adapter can either be a PEX adapter, an ObjectScript adapter or a [python adapter](#75-the-outbound_adapter-class).<br>
655
- Business operation in Python are subclass from iop.BusinessOperation in Python, that inherit from all the functions of the [business host](#73-the-business_host-class).<br>
656
-
657
- ### 6.8.1. The dispacth system
658
- In a business operation it is possbile to create any number of function [similar to the on_message method](#782-the-methods) that will take as argument a [typed request](#711-the-messages) like this `my_special_message_method(self,request: MySpecialMessage)`.
659
-
660
- The dispatch system will automatically analyze any request arriving to the operation and dispacth the requests depending of their type. If the type of the request is not recognized or is not specified in any **on_message like function**, the dispatch system will send it to the `on_message` function.
661
-
662
- ### 6.8.2. The methods
663
- This class defines:
664
-
665
- `on_message`: Called when the business operation receives a message from another production component [that can not be dispatched to another function](#781-the-dispacth-system).<br>
666
- Typically, the operation will either send the message to the external system or forward it to a business process or another business operation.
667
- If the operation has an adapter, it uses the Adapter.invoke() method to call the method on the adapter that sends the message to the external system.
668
- If the operation is forwarding the message to another production component, it uses the SendRequestAsync() or the SendRequestSync() method.<br>
669
- **Parameters**:
670
- - **request**: An instance of either a subclass of Message or of IRISObject containing the incoming message for the business operation.
671
-
672
- **Returns**:
673
- The response object
674
-
675
- Example of a business operation ( situated in the src/python/demo/reddit/bo.py file ):
676
- ```python
677
- from iop import BusinessOperation
678
-
679
- from message import MyRequest,MyMessage
680
-
681
- import iris
682
-
683
- import os
684
- import datetime
685
- import smtplib
686
- from email.mime.text import MIMEText
687
-
688
- class EmailOperation(BusinessOperation):
689
- """
690
- This operation receive a PostMessage and send an email with all the
691
- important information to the concerned company ( dog or cat company )
692
- """
693
-
694
- def my_message(self,request:MyMessage):
695
- sender = 'admin@example.com'
696
- receivers = 'toto@example.com'
697
- port = 1025
698
- msg = MIMEText(request.toto)
699
-
700
- msg['Subject'] = 'MyMessage'
701
- msg['From'] = sender
702
- msg['To'] = receivers
703
-
704
- with smtplib.SMTP('localhost', port) as server:
705
- server.sendmail(sender, receivers, msg.as_string())
706
- print("Successfully sent email")
707
-
708
- def on_message(self, request):
709
-
710
- sender = 'admin@example.com'
711
- receivers = [ request.to_email_address ]
712
-
713
-
714
- port = 1025
715
- msg = MIMEText('This is test mail')
716
-
717
- msg['Subject'] = request.found+" found"
718
- msg['From'] = 'admin@example.com'
719
- msg['To'] = request.to_email_address
720
-
721
- with smtplib.SMTP('localhost', port) as server:
722
-
723
- # server.login('username', 'password')
724
- server.sendmail(sender, receivers, msg.as_string())
725
- print("Successfully sent email")
726
-
727
- ```
728
- If this operation is called using a MyRequest message, the my_message function will be called thanks to the dispatcher, otherwise the on_message function will be called.
729
-
730
- ## 6.9. The `director` class
731
- The Director class is used for nonpolling business services, that is, business services which are not automatically called by the production framework (through the inbound adapter) at the call interval.<br>
732
- Instead these business services are created by a custom application by calling the Director.create_business_service() method.<br>
733
- This class defines:
734
-
735
- `create_business_service`: The create_business_service() method initiates the specified business service.<br>
736
- **Parameters**:
737
- - **connection**: an IRISConnection object that specifies the connection to an IRIS instance for Java.
738
- - **target**: a string that specifies the name of the business service in the production definition.
739
-
740
- **Returns**:
741
- an object that contains an instance of IRISBusinessService
742
-
743
- `start_production`: The start_production() method starts the production.<br>
744
- **Parameters**:
745
- - **production_name**: a string that specifies the name of the production to start.
746
-
747
- `stop_production`: The stop_production() method stops the production.<br>
748
- **Parameters**:
749
- - **production_name**: a string that specifies the name of the production to stop.
750
-
751
- `restart_production`: The restart_production() method restarts the production.<br>
752
- **Parameters**:
753
- - **production_name**: a string that specifies the name of the production to restart.
754
-
755
- `list_productions`: The list_productions() method returns a dictionary of the names of the productions that are currently running.<br>
756
-
757
- ## 6.10. The `objects`
758
- We will use `dataclass` to hold information in our [messages](#711-the-messages) in a `obj.py` file.
759
-
760
- Example of an object ( situated in the src/python/demo/reddit/obj.py file ):
761
- ```python
762
- from dataclasses import dataclass
763
-
764
- @dataclass
765
- class PostClass:
766
- title: str
767
- selftext : str
768
- author: str
769
- url: str
770
- created_utc: float = None
771
- original_json: str = None
772
- ```
773
-
774
- ## 6.11. The `messages`
775
- The messages will contain one or more [objects](#710-the-objects), located in the `obj.py` file.<br>
776
- Messages, requests and responses all inherit from the `iop.Message` class.
777
-
778
- These messages will allow us to transfer information between any business service/process/operation.
779
-
780
- Example of a message ( situated in the src/python/demo/reddit/message.py file ):
781
- ```python
782
- from iop import Message
783
-
784
- from dataclasses import dataclass
785
-
786
- from obj import PostClass
787
-
788
- @dataclass
789
- class PostMessage(Message):
790
- post:PostClass = None
791
- to_email_address:str = None
792
- found:str = None
793
- ```
794
-
795
- WIP It is to be noted that it is needed to use types when you define an object or a message.
796
-
797
- ## 6.12. How to regsiter a component
798
-
799
- You can register a component to iris in many way :
800
- * Only one component with `register_component`
801
- * All the component in a file with `register_file`
802
- * All the component in a folder with `register_folder`
803
-
804
- ### 6.12.1. register_component
805
-
806
- Start an embedded python shell :
807
-
808
- ```sh
809
- /usr/irissys/bin/irispython
810
- ```
811
-
812
- Then use this class method to add a new py file to the component list for interoperability.
813
-
814
- ```python
815
- from iop import Utils
816
- Utils.register_component(<ModuleName>,<ClassName>,<PathToPyFile>,<OverWrite>,<NameOfTheComponent>)
817
- ```
818
-
819
- e.g :
820
- ```python
821
- from iop import Utils
822
- Utils.register_component("MyCombinedBusinessOperation","MyCombinedBusinessOperation","/irisdev/app/src/python/demo/",1,"PEX.MyCombinedBusinessOperation")
823
- ```
824
-
825
- ### 6.12.2. register_file
826
-
827
- Start an embedded python shell :
828
-
829
- ```sh
830
- /usr/irissys/bin/irispython
831
- ```
832
-
833
- Then use this class method to add a new py file to the component list for interoperability.
834
-
835
- ```python
836
- from iop import Utils
837
- Utils.register_file(<File>,<OverWrite>,<PackageName>)
838
- ```
839
-
840
- e.g :
841
- ```python
842
- from iop import Utils
843
- Utils.register_file("/irisdev/app/src/python/demo/bo.py",1,"PEX")
844
- ```
845
-
846
- ### 6.12.3. register_folder
847
-
848
- Start an embedded python shell :
849
-
850
- ```sh
851
- /usr/irissys/bin/irispython
852
- ```
853
-
854
- Then use this class method to add a new py file to the component list for interoperability.
855
-
856
- ```python
857
- from iop import Utils
858
- Utils.register_folder(<Path>,<OverWrite>,<PackageName>)
859
- ```
860
-
861
- e.g :
862
- ```python
863
- from iop import Utils
864
- Utils.register_folder("/irisdev/app/src/python/demo/",1,"PEX")
865
- ```
866
-
867
- ### 6.12.4. migrate
868
-
869
- Start an embedded python shell :
870
-
871
- ```sh
872
- /usr/irissys/bin/irispython
873
- ```
874
-
875
- Then use this static method to migrate the settings file to the iris framework.
876
-
877
- ```python
878
- from iop import Utils
879
- Utils.migrate()
880
- ```
881
-
882
- #### 6.12.4.1. setting.py file
883
-
884
- This file is used to store the settings of the interoperability components.
885
-
886
- It has two sections :
887
- * `CLASSES` : This section is used to store the classes of the interoperability components.
888
- * `PRODUCTIONS` : This section is used to store the productions of the interoperability components.
889
-
890
- e.g :
891
- ```python
892
- import bp
893
- from bo import *
894
- from bs import *
895
-
896
- CLASSES = {
897
- 'Python.RedditService': RedditService,
898
- 'Python.FilterPostRoutingRule': bp.FilterPostRoutingRule,
899
- 'Python.FileOperation': FileOperation,
900
- 'Python.FileOperationWithIrisAdapter': FileOperationWithIrisAdapter,
901
- }
902
-
903
- PRODUCTIONS = [
904
- {
905
- 'dc.Python.Production': {
906
- "@Name": "dc.Demo.Production",
907
- "@TestingEnabled": "true",
908
- "@LogGeneralTraceEvents": "false",
909
- "Description": "",
910
- "ActorPoolSize": "2",
911
- "Item": [
912
- {
913
- "@Name": "Python.FileOperation",
914
- "@Category": "",
915
- "@ClassName": "Python.FileOperation",
916
- "@PoolSize": "1",
917
- "@Enabled": "true",
918
- "@Foreground": "false",
919
- "@Comment": "",
920
- "@LogTraceEvents": "true",
921
- "@Schedule": "",
922
- "Setting": {
923
- "@Target": "Host",
924
- "@Name": "%settings",
925
- "#text": "path=/tmp"
926
- }
927
- },
928
- {
929
- "@Name": "Python.RedditService",
930
- "@Category": "",
931
- "@ClassName": "Python.RedditService",
932
- "@PoolSize": "1",
933
- "@Enabled": "true",
934
- "@Foreground": "false",
935
- "@Comment": "",
936
- "@LogTraceEvents": "false",
937
- "@Schedule": "",
938
- "Setting": [
939
- {
940
- "@Target": "Host",
941
- "@Name": "%settings",
942
- "#text": "limit=10\nother<10"
943
- }
944
- ]
945
- },
946
- {
947
- "@Name": "Python.FilterPostRoutingRule",
948
- "@Category": "",
949
- "@ClassName": "Python.FilterPostRoutingRule",
950
- "@PoolSize": "1",
951
- "@Enabled": "true",
952
- "@Foreground": "false",
953
- "@Comment": "",
954
- "@LogTraceEvents": "false",
955
- "@Schedule": ""
956
- }
957
- ]
958
- }
959
- }
960
- ]
961
- ```
962
-
963
- ##### 6.12.4.1.1. CLASSES section
964
-
965
- This section is used to store the classes of the interoperability components.
966
-
967
- It aims to help to register the components.
968
-
969
- This dictionary has the following structure :
970
- * Key : The name of the component
971
- * Value :
972
- * The class of the component (you have to import it before)
973
- * The module of the component (you have to import it before)
974
- * Another dictionary with the following structure :
975
- * `module` : Name of the module of the component (optional)
976
- * `class` : Name of the class of the component (optional)
977
- * `path` : The path of the component (mandatory)
978
-
979
- e.g :
980
-
981
- When Value is a class or a module:
982
- ```python
983
- import bo
984
- import bp
985
- from bs import RedditService
986
-
987
- CLASSES = {
988
- 'Python.RedditService': RedditService,
989
- 'Python.FilterPostRoutingRule': bp.FilterPostRoutingRule,
990
- 'Python.FileOperation': bo,
991
- }
992
- ```
993
-
994
- When Value is a dictionary :
995
- ```python
996
- CLASSES = {
997
- 'Python.RedditService': {
998
- 'module': 'bs',
999
- 'class': 'RedditService',
1000
- 'path': '/irisdev/app/src/python/demo/'
1001
- },
1002
- 'Python.Module': {
1003
- 'module': 'bp',
1004
- 'path': '/irisdev/app/src/python/demo/'
1005
- },
1006
- 'Python.Package': {
1007
- 'path': '/irisdev/app/src/python/demo/'
1008
- },
1009
- }
1010
- ```
1011
-
1012
- ##### 6.12.4.1.2. Productions section
1013
-
1014
- This section is used to store the productions of the interoperability components.
1015
-
1016
- It aims to help to register a production.
1017
-
1018
- This list has the following structure :
1019
- * A list of dictionary with the following structure :
1020
- * `dc.Python.Production` : The name of the production
1021
- * `@Name` : The name of the production
1022
- * `@TestingEnabled` : The testing enabled of the production
1023
- * `@LogGeneralTraceEvents` : The log general trace events of the production
1024
- * `Description` : The description of the production
1025
- * `ActorPoolSize` : The actor pool size of the production
1026
- * `Item` : The list of the items of the production
1027
- * `@Name` : The name of the item
1028
- * `@Category` : The category of the item
1029
- * `@ClassName` : The class name of the item
1030
- * `@PoolSize` : The pool size of the item
1031
- * `@Enabled` : The enabled of the item
1032
- * `@Foreground` : The foreground of the item
1033
- * `@Comment` : The comment of the item
1034
- * `@LogTraceEvents` : The log trace events of the item
1035
- * `@Schedule` : The schedule of the item
1036
- * `Setting` : The list of the settings of the item
1037
- * `@Target` : The target of the setting
1038
- * `@Name` : The name of the setting
1039
- * `#text` : The value of the setting
1040
-
1041
- The minimum structure of a production is :
1042
- ```python
1043
- PRODUCTIONS = [
1044
- {
1045
- 'UnitTest.Production': {
1046
- "Item": [
1047
- {
1048
- "@Name": "Python.FileOperation",
1049
- "@ClassName": "Python.FileOperation",
1050
- },
1051
- {
1052
- "@Name": "Python.EmailOperation",
1053
- "@ClassName": "UnitTest.Package.EmailOperation"
1054
- }
1055
- ]
1056
- }
1057
- }
1058
- ]
1059
- ```
1060
-
1061
- You can also set in `@ClassName` an item from the CLASSES section.
1062
-
1063
- e.g :
1064
- ```python
1065
- from bo import FileOperation
1066
- PRODUCTIONS = [
1067
- {
1068
- 'UnitTest.Production': {
1069
- "Item": [
1070
- {
1071
- "@Name": "Python.FileOperation",
1072
- "@ClassName": FileOperation,
1073
- }
1074
- ]
1075
- }
1076
- }
1077
- ]
1078
- ```
1079
-
1080
- As the production is a dictionary, you can add in value of the production dictionary an environment variable.
1081
-
1082
- e.g :
1083
- ```python
1084
- import os
1085
-
1086
- PRODUCTIONS = [
1087
- {
1088
- 'UnitTest.Production': {
1089
- "Item": [
1090
- {
1091
- "@Name": "Python.FileOperation",
1092
- "@ClassName": "Python.FileOperation",
1093
- "Setting": {
1094
- "@Target": "Host",
1095
- "@Name": "%settings",
1096
- "#text": os.environ['SETTINGS']
1097
- }
1098
- }
1099
- ]
1100
- }
1101
- }
1102
- ]
1103
- ```
1104
-
1105
- ## 6.13. Direct use of IOP
1106
-
1107
- If you don't want to use the register_component util. You can add a IOP.BusinessService component directly into the management portal and configure the properties :
1108
- - %module :
1109
- - Module name of your python code
1110
- - %classname :
1111
- - Classname of you component
1112
- - %classpaths
1113
- - Path where you component is.
1114
- - This can one or more Classpaths (separated by '|' character) needed in addition to PYTHON_PATH
1115
-
1116
- e.g :
1117
- <img width="800" alt="component-config" src="https://user-images.githubusercontent.com/47849411/131316308-e1898b19-11df-433b-b1c6-7f69d5cc9974.png">
1118
-
1119
- # 7. Command line
1120
-
1121
- Since version 2.3.1, you can use the command line to register your components and productions.
1122
-
1123
- To use it, you have to use the following command :
1124
- ```bash
1125
- iop
1126
- ```
1127
-
1128
- output :
1129
- ```bash
1130
- usage: python3 -m iop [-h] [-d DEFAULT] [-l] [-s START] [-k] [-S] [-r] [-M MIGRATE] [-e EXPORT] [-x] [-v] [-L]
1131
- optional arguments:
1132
- -h, --help display help and default production name
1133
- -d DEFAULT, --default DEFAULT
1134
- set the default production
1135
- -l, --lists list productions
1136
- -s START, --start START
1137
- start a production
1138
- -k, --kill kill a production (force stop)
1139
- -S, --stop stop a production
1140
- -r, --restart restart a production
1141
- -M MIGRATE, --migrate MIGRATE
1142
- migrate production and classes with settings file
1143
- -e EXPORT, --export EXPORT
1144
- export a production
1145
- -x, --status status a production
1146
- -v, --version display version
1147
- -L, --log display log
1148
-
1149
- default production: PEX.Production
1150
- ```
1151
-
1152
- ## 7.1. help
1153
-
1154
- The help command display the help and the default production name.
1155
-
1156
- ```bash
1157
- iop -h
1158
- ```
1159
-
1160
- output :
1161
- ```bash
1162
- usage: python3 -m iop [-h] [-d DEFAULT] [-l] [-s START] [-k] [-S] [-r] [-M MIGRATE] [-e EXPORT] [-x] [-v] [-L]
1163
- ...
1164
- default production: PEX.Production
1165
- ```
1166
-
1167
- ## 7.2. default
1168
-
1169
- The default command set the default production.
1170
-
1171
- With no argument, it display the default production.
1172
-
1173
- ```bash
1174
- iop -d
1175
- ```
1176
-
1177
- output :
1178
- ```bash
1179
- default production: PEX.Production
1180
- ```
1181
-
1182
- With an argument, it set the default production.
1183
-
1184
- ```bash
1185
- iop -d PEX.Production
1186
- ```
1187
-
1188
- ## 7.3. lists
1189
-
1190
- The lists command list productions.
1191
-
1192
- ```bash
1193
- iop -l
1194
- ```
1195
-
1196
- output :
1197
- ```bash
1198
- {
1199
- "PEX.Production": {
1200
- "Status": "Stopped",
1201
- "LastStartTime": "2023-05-31 11:13:51.000",
1202
- "LastStopTime": "2023-05-31 11:13:54.153",
1203
- "AutoStart": 0
1204
- }
1205
- }
1206
- ```
1207
-
1208
- ## 7.4. start
1209
-
1210
- The start command start a production.
1211
-
1212
- To exit the command, you have to press CTRL+C.
1213
-
1214
- ```bash
1215
- iop -s PEX.Production
1216
- ```
1217
-
1218
- output :
1219
- ```bash
1220
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting production
1221
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.FileOperation
1222
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.EmailOperation
1223
- ...
1224
- ```
1225
-
1226
- ## 7.5. kill
1227
-
1228
- The kill command kill a production (force stop).
1229
-
1230
- Kill command is the same as stop command but with a force stop.
1231
-
1232
- Kill command doesn't take an argument because only one production can be running.
1233
-
1234
- ```bash
1235
- iop -k
1236
- ```
1237
-
1238
- ## 7.6. stop
1239
-
1240
- The stop command stop a production.
1241
-
1242
- Stop command doesn't take an argument because only one production can be running.
1243
-
1244
- ```bash
1245
- iop -S
1246
- ```
1247
-
1248
- ## 7.7. restart
1249
-
1250
- The restart command restart a production.
1251
-
1252
- Restart command doesn't take an argument because only one production can be running.
1253
-
1254
- ```bash
1255
- iop -r
1256
- ```
1257
-
1258
- ## 7.8. migrate
1259
-
1260
- The migrate command migrate a production and classes with settings file.
1261
-
1262
- Migrate command must take the absolute path of the settings file.
1263
-
1264
- Settings file must be in the same folder as the python code.
1265
-
1266
- ```bash
1267
- iop -M /tmp/settings.py
1268
- ```
1269
-
1270
- ## 7.9. export
1271
-
1272
- The export command export a production.
1273
-
1274
- If no argument is given, the export command export the default production.
1275
-
1276
- ```bash
1277
- iop -e
1278
- ```
1279
-
1280
- If an argument is given, the export command export the production given in argument.
1281
-
1282
- ```bash
1283
- iop -e PEX.Production
1284
- ```
1285
-
1286
- output :
1287
- ```bash
1288
- {
1289
- "Production": {
1290
- "@Name": "PEX.Production",
1291
- "@TestingEnabled": "true",
1292
- "@LogGeneralTraceEvents": "false",
1293
- "Description": "",
1294
- "ActorPoolSize": "2",
1295
- "Item": [
1296
- {
1297
- "@Name": "Python.FileOperation",
1298
- "@Category": "",
1299
- "@ClassName": "Python.FileOperation",
1300
- "@PoolSize": "1",
1301
- "@Enabled": "true",
1302
- "@Foreground": "false",
1303
- "@Comment": "",
1304
- "@LogTraceEvents": "true",
1305
- "@Schedule": "",
1306
- "Setting": [
1307
- {
1308
- "@Target": "Adapter",
1309
- "@Name": "Charset",
1310
- "#text": "utf-8"
1311
- },
1312
- {
1313
- "@Target": "Adapter",
1314
- "@Name": "FilePath",
1315
- "#text": "/irisdev/app/output/"
1316
- },
1317
- {
1318
- "@Target": "Host",
1319
- "@Name": "%settings",
1320
- "#text": "path=/irisdev/app/output/"
1321
- }
1322
- ]
1323
- }
1324
- ]
1325
- }
1326
- }
1327
- ```
1328
-
1329
- ## 7.10. status
1330
-
1331
- The status command status a production.
1332
-
1333
- Status command doesn't take an argument because only one production can be running.
1334
-
1335
- ```bash
1336
- iop -x
1337
- ```
1338
-
1339
- output :
1340
- ```bash
1341
- {
1342
- "Production": "PEX.Production",
1343
- "Status": "stopped"
1344
- }
1345
- ```
1346
-
1347
- Status can be :
1348
- - stopped
1349
- - running
1350
- - suspended
1351
- - troubled
1352
-
1353
- ## 7.11. version
1354
-
1355
- The version command display the version.
1356
-
1357
- ```bash
1358
- iop -v
1359
- ```
1360
-
1361
- output :
1362
- ```bash
1363
- 2.3.0
1364
- ```
1365
-
1366
- ## 7.12. log
1367
-
1368
- The log command display the log.
1369
-
1370
- To exit the command, you have to press CTRL+C.
1371
-
1372
- ```bash
1373
- iop -L
1374
- ```
1375
-
1376
- output :
1377
- ```bash
1378
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting production
1379
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.FileOperation
1380
- 2021-08-30 15:13:51.000 [PEX.Production] INFO: Starting item Python.EmailOperation
1381
- ...
1382
- ```
1383
-
1384
- # 8. Credits
1385
-
1386
- Most of the code came from PEX for Python by Mo Cheng and Summer Gerry.
1387
-
1388
- Works only on IRIS 2021.2 +
1389
-
1390
- # 9. Benchmarks
1391
-
1392
- 8 senarios with thoses parameters :
1393
- - 100 messages
1394
- - body : simple string `test`
1395
-
1396
- | Scenario | Time (s) |
1397
- | --- | --- |
1398
- | Python BP to Python BO with Iris Message | 0.739 |
1399
- | Python BP to Python BO with Python Message | 0.732 |
1400
- | ObjetScript BP to Python BO with Iris Message | 0.594 |
1401
- | ObjetScript BP to Python BO with Python Message | 0.642 |
1402
- | Python BP to ObjetScript BO with Iris Message | 0.642 |
1403
- | Python BP to ObjetScript BO with Python Message | 0.675 |
1404
- | ObjetScript BP to ObjetScript BO with Iris Message | 0.159 |
1405
- | ObjetScript BP to ObjetScript BO with Python Message | 0.182 |