$ python --version
Python 3.6.5 :: Anaconda custom (64-bit)
>>> flask.__version__
'1.0.2'
>>> requests.__version__
'2.18.4'
You can simply install dependencies with pip
or conda
:
$ # Use one of the following command:
$ pip install -r requirements.txt
$ conda install --yes --file requirements.txt
(Have better experience on Linux, MacOS, Cygwin and MSYS.)
- Simple Demo (Pass)
- Simple Strict Demo (Use Whiteboard) (Pass)
- Cancel Order Demo (Pass)
The whiteboard is an optional part for an artifact. It keeps the records and the snapshot for the whole artifact.
Click here to see more about the usage.
And you need to configure the engine is you want to use the whiteboard (See here).
root
or Administrator
permission may be needed.
-
Default: (Use
setting.py
as the config file.)$ python main.py # Or you can change the name of `main.py`.
-
For External, you can use
external_main.py
:$ python external_main.py # Or you can change the name of `external_main.py`.
Attention: When use
external_main.py
, the name ofmain.py
can not be changed. -
Use
some-folder/another-folder/some-file.py
as the config file:$ python main.py some-folder.another-folder.some-file
Attention:
some-folder/another-folder/some-file.py
should have module structure. Namely,import some-folder.another-folder.some-file
can be executed properly in Python.Use
setting.py
as the config file:$ python main.py setting
Configure setting.py
(Or another file name):
All the machines in one artifact share the same public part, namely, the following two variables:
messages_paths: dict
machines_addresses: dict
whiteboard_address: str # Optional (If you want to use the whiteboard, then you shall configure this field.)
-
Type
messages_paths :: Dict String (String, String) machines_address :: Dict String String whiteboard_address :: String -- Optional
# For type_checker.py: messages_paths_type = {str: (str, str)} machines_address_type = {str: str} whiteboard_address_type = str # Optional
-
Content
messages_paths: dict = { message_type: (from_entity_type, to_entities_type) } machines_addresses: dict = { machine_name : ip_address } whiteboard_address: str = 'http://whiteboard.addr' # Optional
-
Example
messages_paths: dict = { 'OrderCancel': ('External', 'Order'), 'ReshippingBack': ('Order', 'External'), 'CancelPurchase': ('Order', 'Purchase'), 'CancelFulfillment': ('Order', 'Fulfillment') } machines_addresses: dict = { 'Order': 'http://192.168.1.1:3000', 'Purchase': 'http://192.168.1.2', 'Fulfillment': 'http://192.168.1.3:8000', 'Payment': 'http://192.168.1.4:80' } whiteboard_address: str = 'http://192.168.1.5:80' # Optional
The artifact on each machine:
listen_port: int
entity_type: str
machine_name: str
entity_default_data: dict
messages_to_receive: dict
And here is an optional part for External
:
Only when use external_main.py
, you need and shall config the following 2 items:
begin_message: str
begin_message_to_entities_ids_chooser: function
-
Type
listen_port :: Int entity_type :: String machine_name :: String entity_default_data :: JsonDict messages_to_receive :: Dict String (String -> String -> (), ([String], JsonDict -> Bool, [(String, Int -> JsonDict -> [Int], JsonDict -> JsonDict)])) begin_message :: String begin_message_to_entities_ids_chooser :: Int -> JsonDict -> [Int]
# For type_checker.py: listen_port_type = int entity_type_type = str machine_name_type = str entity_default_data_type = dict messages_to_receive_type = {str: (function_type, ([str], function_type, [(str, function_type, function_type)]))} begin_message_type = str begin_message_to_entities_ids_chooser_type = function_type
-
Content
listen_port = some_port_number entity_type = 'some_entity_type' machine_name = entity_type entity_default_data = {} messages_to_receive = { message_type: ( () => data_handler(message_data, entity_data), ( snapshot_to_meet, // The business entity_data => bool, // to meet [(message_type, (entity_id, entity_data) => ids_list, entity_data => send_data)] ) ) } begin_message_type = 'begin_message_type' begin_message_to_entities_ids_chooser_type = (entity_id, entity_data) => ids_list
-
Attention 1:
entity_type
should be equal tomachine_name
. -
Attention 2: There is a strict mode for
snapshot_to_meet
. In the strict mode, the snapshot meets only ifsnapshot_to_meet
is the same as the snapshot in an entity. To enable the strict mode, just makesnapshot_to_meet[0]
the empty string''
.For example:
-
Both
snapshot_to_meet = ['A']
(nonstrict mode) andsnapshot_to_meet = ['A', 'B']
(nonstrict mode) meets the entity snapshot['A', 'B', 'C']
. -
snapshot_to_meet = ['A', 'B', 'C', 'D']
(nonstrict mode) does not meet the entity snapshot['A', 'B', 'C']
. -
snapshot_to_meet = ['', 'A']
(strict mode),snapshot_to_meet = ['', 'A', 'B']
(strict mode) andsnapshot_to_meet = ['', 'A', 'B', 'C', 'D']
(strict mode) do not meet the entity snapshot['A', 'B', 'C']
. -
In the strict mode, only
snapshot_to_meet = ['', 'A', 'B', 'C']
meets the entity snapshot['A', 'B', 'C']
.
-
-
-
Example
listen_port = 5000 entity_type = 'Payment' machine_name = entity_type entity_default_data = {} messages_to_receive = { 'PaymentCancel': ( payment_cancel_data_handler, ( ['PaymentCancel'], lambda _: True, [('OrderPaymentUndone', payment_cancel_get_to_ids_list, lambda _: {})] ) ) } def payment_cancel_data_handler(message_data, entity_data): return def payment_cancel_get_to_ids_list(from_entity_id, from_entity_data) -> list: pass # This function presents the relationships.
Click Here: Message Format