{"id":18448783,"url":"https://github.com/minhtuan221/microservices-connector","last_synced_at":"2025-04-08T01:32:35.106Z","repository":{"id":57441555,"uuid":"124891513","full_name":"minhtuan221/Microservices-connector","owner":"minhtuan221","description":"Inter-Service communication framework, support for microservice architecture and distributed system","archived":false,"fork":false,"pushed_at":"2019-01-23T06:48:59.000Z","size":148,"stargazers_count":17,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-18T20:07:29.474Z","etag":null,"topics":["communication","decentralized","distributed-systems","flask","microservice","microservice-connector","microservices-architecture","python","requests","sanic","scalability","stable"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/minhtuan221.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-12T13:14:43.000Z","updated_at":"2023-05-09T09:13:40.000Z","dependencies_parsed_at":"2022-09-06T02:30:10.986Z","dependency_job_id":null,"html_url":"https://github.com/minhtuan221/Microservices-connector","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhtuan221%2FMicroservices-connector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhtuan221%2FMicroservices-connector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhtuan221%2FMicroservices-connector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/minhtuan221%2FMicroservices-connector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/minhtuan221","download_url":"https://codeload.github.com/minhtuan221/Microservices-connector/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247760614,"owners_count":20991512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["communication","decentralized","distributed-systems","flask","microservice","microservice-connector","microservices-architecture","python","requests","sanic","scalability","stable"],"created_at":"2024-11-06T07:17:12.735Z","updated_at":"2025-04-08T01:32:34.828Z","avatar_url":"https://github.com/minhtuan221.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Microservices Connector\nMicroservices Connector is a Inter-Service communication framework, support for microservice architecture and distributed system.\n\n## Getting Started\n\n__Microservices__ is a way of breaking large software projects into loosely coupled modules, which communicate with each other through simple APIs. The advantages of microservices are improves fault isolation, scalability, Ease of development. It convinced some big enterprise players – like Amazon, Netflix, and eBay – to begin their transitions. \n\n_Microservices Connector_ is a Inter-Service communication framework written in python, support for microservice architecture and distributed system. Its features contain:\n* Transfering data as returning a function results or quering data.\n* Support transfer multiple values with many type as string, int, float, list, dict, class attribute\n* Do not require knowledge about web/http connection or touch to them\n* Distributed system\n\n![alt text](images/Distributed-system.jpeg  \"Illustration of network system. Source:medium.com\")\n\nIllustration of network system. Source:medium.com\n\nAs illustration, distributed systems are very stable and Infinite scalability. But distributed systems are the most difficult to maintain.\n\n_Microservices Connector_ supports communication by the following framework:\n* flask - A micro web framework\n* Sanic - Gotta go fast (A async web framework)\n### Quickstart:\n\nMicroservices Connector is available on pip. You can install via pip (require python\u003e=3.5):\n\n```\npip install microservices_connector\n```\nStart project by a minimum example: \n\n* Step 1: Create 1 file name app1.py, write and save with the code below\n\n```python\nfrom microservices_connector.Interservices import Microservice\n\nMicro = Microservice(__name__)\n\n@Micro.typing('/helloworld')\n@Micro.reply\ndef helloworld(name):\n    return 'Welcome %s' % (name)\n\nif __name__ == '__main__':\n    Micro.run()\n```\n\n* Step 2: Create 1 file name app2.py, write and save with the code below\n\n```python\nfrom microservices_connector.Interservices import Friend\n\naFriend= Friend('app1', 'http://0.0.0.0:5000')\nmessage = aFriend.send('/helloworld','Mr. Developer')\nprint(message)\n```\n* Step 3: Run app1.py and app2.py together.\n\nOpen a terminal in the same folder with them and run:\n`python app1.py`.\n\nOpen another terminal in the same folder and run:\n`python app2.py`\n\nYou get the result: `Welcome Mr. Developer` in terminal of app2.py. This is no difference if you do `from .app1 import helloword; message = helloworld('Mr. Developer'); print(message)`. Note: To stop app1, open its terminal and Ctrl + C. The example can be found in `test/example00` folder\n\n**Explanation**: App1 and app2 are small example of microservice system. In the example, **M** in app1 is listener, a http server while __F__ in app2 is sender. Listener and sender are isolated design, they can work seperately or together in an app/service. A microservice can be a listener of many other microservices or sender of many other microservices or both of them. A standard microservice mention in this project contain both listener and sender.\n\n## Tutorial\n\n### 1. Start your first app\n\nIn the tutorial, we assume you have this code in the top of your file.\n\n```python\nfrom microservices_connector.Interservices import Microservice\n\nMicro = Microservice(__name__)\n\n# for Sanic framework if you want to use sanic instead of flask\nfrom microservices_connector.Interservices import SanicApp as Microservice\n\nMicro = Microservice(__name__)\n```\n\nNow, look closer at `Microservice(__name__)`, it actually look like this: \n    \n    Microservice(name, port: int=5000, host: str='0.0.0.0', debug=None, token: dict = {}, secretKey=None)\n    \nArguments:\n* name {str} -- Require a name for your app, recommend put `__name__` for it\n* port {int} -- Choose from 3000 to 9000, default to 5000\n* host {str} -- Host ip, Default 0.0.0.0 for localhost\n* debug {boolean} -- True for development, False/None for production\n* token {dict} -- A dict contain all rule and its token. It can be set later\n\nThe class Microservice is used to create a listener/a microservice. In a file/app, you should only have one listener. About parameters, If you aren't familiar with http server, you only need remember:\n* One app should have only one listener\n* Should use `__name__` for name and name need to be unique\n* If you run multiple listener, use only one unique port for each listener. for example:\n\n```python\nM1 = Microservice(__name__, port=5010) # in file app1\nM2 = Microservice(__name__, port=5020) # in file app2\n```\nNote: You should be carefully if there are other web applications running in your port/server.\n\n### 2. Way of running an app\n\nA sender is a python def, so you can put it anywhere in your app. Listener is a http server so it's a bit difference from other.\n\nOption 1: Use if/main in the end of startup file (file that you start your project by `python \u003cfilename\u003e`). Add the following code the end:\n```python\n# Micro is your Microservice Object\nif __name__ == '__main__':\n    Micro.run()\n```\n\nOption 2: Create a file name run.py and run your app from this file. For example, we create a run.py in the same folder of app1.py in the first example. It will be like this:\n```python\nfrom app1 import Micro\n\nif __name__ == '__main__':\n    Micro.run(port=5000, host='0.0.0.0', debug=True)\n```\nOption 2 is more appreciated. It avoid the app looping from them self, so get away of stunning your app. If you have 2 app in a server/computer, you should create 2 run file for it. Don't for get `Ctrl + C` to stop your app.\n\nNote: _We assume you already use one of the options above for your code_. This tutorial focuses on communication between 'service-to-service' as def function, not http connect.\n\n### 3. Send, Typing and reply\n\nThink like a human, if you want to communicate with some friend in facebook, you will open *messenger*, find your friend and send a message to them. It's a way of sending message to each other. Then, your friend will type a message and reply you. The process is similar here. See the code:\n```python\naFriend= Friend('Corgi', 'http://0.0.0.0:5000') # this is: you're finding friend in your head. \n# You can call him with a cute name like 'Puppy','Teddy' or 'Corgi'. \n# But you must always remember his real-name is 'http://0.0.0.0:5000' to know actually who he is\n\nmessage = aFriend.send('/helloworld','Mr. Close friend') # then you can send him a message\n```\n\n`/helloworld` is the rule/topic you say/ask to a friend or the route in http. It need to start with `/`. The rule must match with the rule of `Typing` to be replied. `Mr. Close friend` is what you are talking about, which can be string, integer, float, list, dict or class. For example: `aFriend.send('/topic',variable1, variable2, keyword1='secret key')`\n\nIn other side, your friend or a microservice or a listener has the following process:\n```python\n@Micro.typing('/helloworld') # this is the rule/topic he knows. If he don't know, he cannot reply\n@Micro.reply # he is replying\ndef helloworld(name): # this is the process in side his head\n    return 'Welcome %s' % (name) # the answer\n```\n\n`@Micro.typing` - The rule/topic must exactly match with the topic was sent and should startwith \"/\". The `@Micro.reply` must come before def. Then, Microservice handles the remain. Next chapter is about returning data\n\n### 4. Send and reply string, integer, float\n\nIn the sender side, you can send data type as the code below:\n```python\nprint(\n    \"\"\"##############################\n    Test return string\n    \"\"\")\naFriend= Friend('app1', 'http://localhost:5000')\nprint('Test: return a simple string')\nx = aFriend.send('/str', 'A variable value', key='A keyword variable value')\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return multiple string')\nx, y, z = aFriend.send('/str2', 'A variable value',\n                key='A keyword variable value')\nprint('x=' ,x, type(x))\nprint('y=', y, type(y))\nprint('z=', z, type(z))\n\nprint(\n    \"\"\"##############################\n    Test return a int, float\n    \"\"\")\naFriend= Friend('app1', 'http://localhost:5000')\nprint('Test: return a simple Value')\nx = aFriend.send('/int', 2018, key=312)\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return a simple Value')\nx = aFriend.send('/float', 2.018, key=3.12)\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return multiple Value')\nx, y, z = aFriend.send('/int3', 3.1427,\n                    key=1000000000)\nprint('x=', x, type(x))\nprint('y=', y, type(y))\nprint('z=', z, type(z))\n```\nIn the listener, you can reply/return data type as string, integer, float as below:\n```python\n# run a normal function in python\nprint('one cat here')\n\n# return string\n@Micro.typing('/str')\n@Micro.reply\ndef string1(a,key):\n    return a+'-'+key\n\n# return multiple string\n@Micro.typing('/str2')\n@Micro.reply\ndef string2(a, key):\n    return a, key, a+'-'+key\n\n# return Integer and float\n@Micro.typing('/int')\n@Micro.reply\ndef int1(a, key):\n    return a+key\n\n@Micro.typing('/float')\n@Micro.reply\ndef float2(a, key):\n    return a+key\n\n\n@Micro.typing('/int3')\n@Micro.reply\ndef int3(a, key):\n    return a+key, key*key, a*a\n```\nAfter that, first run listener then run sender. We have results (see example01):\n```\nTest: return a simple string\nx= A variable value-A keyword variable value \u003cclass 'str'\u003e\n==========================\nTest: return multiple string\nx= A variable value \u003cclass 'str'\u003e\ny= A keyword variable value \u003cclass 'str'\u003e\nz= A variable value-A keyword variable value \u003cclass 'str'\u003e\n'testStr'  23.17 ms\nTest: return a simple Value\nx= 2330 \u003cclass 'int'\u003e\n==========================\nTest: return a simple Value\nx= 5.138 \u003cclass 'float'\u003e\n==========================\nTest: return multiple Value\nx= 1000000003.1427 \u003cclass 'float'\u003e\ny= 1000000000000000000 \u003cclass 'int'\u003e\nz= 9.87656329 \u003cclass 'float'\u003e\n```\nNote: print('one cat here') print in the screen of listener. You can run any other python function, python code as normal in listener.\n\n### 5. Send and reply list, dict\n\nIn the sender side, you can send data type as the code below:\n```python\nprint(\n    \"\"\"##############################\n    Test return a list, dict\n    \"\"\")\naFriend= Friend('app1', 'http://localhost:5000')\nprint('Test: return a simple Value')\nx = aFriend.send('/list', [12,34,45], key=['abc','zyz'])\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return a simple Value')\nx = aFriend.send('/dict', {'keyword':['anything']}, key={'int':20,'str':'adfafsa','float':0.2323})\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return multiple Value')\nx, y, z = aFriend.send('/list3', {'keyword': ['anything']},\n                    key=['abc', 'zyz'])\nprint('x=', x, type(x))\nprint('y=', y, type(y))\nprint('z=', z, type(z))\n```\nIn the listener, you can reply/return data type as string, integer, float as below:\n```python\n# test return list and dict\n@Micro.typing('/list')\n@Micro.reply\ndef list1(a, key):\n    a.extend(key)\n    return a\n\n\n@Micro.typing('/dict')\n@Micro.reply\ndef dict1(a, key):\n    key['dict'] = a\n    return key\n\n\n@Micro.typing('/list3')\n@Micro.reply\ndef list3(a, key):\n    key.append('other value')\n    c = None\n    return a, key, c\n```\nAfter that, first run listener then run sender. We have results (for full example see tests/example01):\n```\nTest: return a simple Value\nx= [12, 34, 45, 'abc', 'zyz'] \u003cclass 'list'\u003e\n==========================\nTest: return a simple Value\nx= {'dict': {'keyword': ['anything']}, 'float': 0.2323, 'int': 20, 'str': 'adfafsa'} \u003cclass 'dict'\u003e\n==========================\nTest: return multiple Value\nx= {'keyword': ['anything']} \u003cclass 'dict'\u003e\ny= ['abc', 'zyz', 'other value'] \u003cclass 'list'\u003e\nz= None \u003cclass 'NoneType'\u003e\n'testListDict'  22.19 ms\n```\n\n### 6. Send and reply void, Nonetype, class attributes and use of token\nIn the sender side, you can send data type as the code below:\n\n```python\nprint(\n\"\"\"##############################\nTest return NoneType, Class, use of Token\n\"\"\")\naFriend= Friend('app1', 'http://localhost:5000')\nprint('Test: return a simple Value')\nx = aFriend.send('/None', [12, 34, 45], key=['abc', 'zyz'])\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return a simple Value with token')\naFriend.setRule('/class', token='123456')\nx = aFriend.send('/class', {'keyword': ['anything']},\n            key={'int': 20, 'str': 'adfafsa', 'float': 0.2323})\nprint('x=', x, type(x))\nprint('==========================')\nprint('Test: return multiple Value')\naFriend.setRule('/class2', token='123456')\nx,y,z = aFriend.send('/class2', {'keyword': ['anything']},\n            key={'int': 20, 'str': 'adfafsa', 'float': 0.2323})\nprint('x=', x, type(x))\nprint('y=', y, type(y))\nprint('z=', z, type(z))\n\n# Test send class and list of class object\nprint('\\n Test: send class and list of class object')\naFriend.setRule('/class3', token='123456')\nt1 = testservice('value1')\nt2 = testservice('value2')\nx, y, z = aFriend.send('/class3', [t1,t2],\n                    key={'t1': t1, 't2': t2, 'list': [t1, t2]})\nprint('x=', x, type(x))\nprint('y=', y, type(y))\nprint('z=', z, type(z))\n```\n\nIn the listener, you can reply/return data type as string, integer, float as below:\n\n```python\n# return None, class Object\n@Micro.typing('/None')\n@Micro.reply\ndef TestNoneValue(a, key):\n    key.append('Do something in the server')\n\nclass testservice(object):\n    name = 'test'\n    Purpose = 'For test only'\n    empty = None\n    def __init__(self, value):\n        self.value = value\n\n    def onemethod(self):\n        pass\n\n\n@Micro.typing('/class',token='123456')\n@Micro.reply\ndef TestClass(a, key):\n    t = testservice(a)\n    return t\n\n\n@Micro.typing('/class2', token='123456')\n@Micro.reply\ndef TestClass2(a, key):\n    t = testservice(key)\n    return t, a, None\n\n@Micro.typing('/class3', token='123456')\n@Micro.reply\ndef TestClass3(a, key):\n    x = testservice(key)\n    y = testservice(a)\n    z = [y,x]\n    return x, y, z \n```\nAfter that, first run listener then run sender. We have results (for full example see tests/example01):\n\n```\n##############################\nTest return NoneType, Class, use of Token\n\nTest: return a simple Value\nx= None \u003cclass 'NoneType'\u003e\n==========================\nTest: return a simple Value with token\nx= {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': {'keyword': ['anything']}} \u003cclass 'dict'\u003e\n==========================\nTest: return multiple Value\nx= {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': {'float': 0.2323, 'int': 20, 'str': 'adfafsa'}} \u003cclass 'dict'\u003e\ny= {'keyword': ['anything']} \u003cclass 'dict'\u003e\nz= None \u003cclass 'NoneType'\u003e\n\nTest: send class and list of class object\nx= {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': {'list': [{'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}], 't1': {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, 't2': {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}}} \u003cclass 'dict'\u003e\ny= {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': [{'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}]} \u003cclass 'dict'\u003e\nz= [{'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': [{'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}]}, {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': {'list': [{'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}], 't1': {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value1'}, 't2': {'Purpose': 'For test only', 'empty': None, 'name': 'test', 'value': 'value2'}}}] \u003cclass 'list'\u003e\n'testClassType'  19.20 ms\n```\n\nNew feature from 0.2.4, now you can send and receive json similar to dict. It helps more readable response\n\n```python\n# in client side\nprint('=================Response json===============')\nx = aFriend.json('/json', a=12,b='This is a text',c={'dict':'a dict'})\nprint('Synchonous POST:', x)\ny = aFriend.json('/json1', method='GET' , a={'dict': 'a only dict'})\nprint('Asynchonous GET:', y)\nz = aFriend.json('/json1', a={'dict': 'a only dict'})\nprint('Asynchonous POST:', z)\n```\nIn the server side we have:\n\n```python\n# in server side\n@Micro.typing('/json')\n@Micro.json\n@timeit\ndef TestReceiveJson(a=1, b='string',c=None):\n    return {'1':a,'2':b,'3':c}\n\n\n# for async request (only apply to sanic)\n@Micro.route('/json1', methods=['GET','POST'])\n@Micro.async_json\nasync def TestReceiveJson2(a=None):\n    return a\n```\n\nYou can response with get, post, put, delete,... as the method above. The result:\n\n```\n=================Response json===============\nSynchonous POST: {'1': 12, '2': 'This is a text', '3': {'dict': 'a dict'}}\nAsynchonous GET: {'dict': 'a only dict'}\nAsynchonous POST: {'dict': 'a only dict'}\n```\n### 7. From 0.2.7, we support for websocket connection:\nIn the sender side, we can send data type as the code below:\n\n```python\nfrom microservices_connector.minisocket import SocketServer\nsk = SocketServer(__name__)\n@sk.router('/hello')\ndef test(message):\n    print(message)\n    return 'ok:'+message\n\ndef main():\n    sk.run()\n    # you can put a flask server here\n    # Socket Server run in a seperate threads, not affect flask server\n\nif __name__ == '__main__':\n    main()\n```\nThe other option is run minisocket in a different thread, that will alow flask server run seperately.\n\n```python\nsk = SocketServer(__name__)\napp = Microservice('Flask_app').app\n\n@app.route('/')\ndef helloworld():\n    time.sleep(2)\n    return 'Sleep 2s before response'\n\n\n@sk.router('/hello')\ndef test(message):\n    print(message)\n    return 'ok:'+message\n\ndef socket_runner():\n    sk.run()\n\ndef main():\n    socket_runner()\n    print('start web framework')\n    app.run()\n\n\nif __name__ == '__main__':\n    main()\n\n```\n\nIn the client side, we create a socket connection using websocket framework:\n\n```python\nimport asyncio\nimport websockets\n\n\nasync def hello():\n    async with websockets.connect('ws://localhost:8765/hello') as websocket:\n        name = input(\"What's your name? \")\n        await websocket.send(name)\n        print(f\"\u003e {name}\")\n        greeting = await websocket.recv()\n        print(f\"\u003c {greeting}\")\n        while greeting != 'close':\n            name = input(\"What's your name? \")\n            await websocket.send(name)\n            greeting = await websocket.recv()\n            print(f\"\u003c {greeting}\")\n\nasyncio.get_event_loop().run_until_complete(hello())\n```\n### 8. From 0.2.7, we support concurrency process with sequences throught DistributedThreads and DistributedProcess :\n\nThis give a solution for the problems of concurrency process that many workers simutanously impact/input to a single database row/table/position or the problem of arbitrary order of data. \nFirst, if you don't need process a data or queue with order or your data do not input to the same database row/table, you should use celery or other framework to scale your project. For that instance, this framework will provide no more efficient than celery which highly use by now.\nSecond, framework need a key for each row/item in data for knowning which want to be ordered. The guide as example below. You need a output_queue for listening the result and continue other function.\n\n```python\nfrom microservices_connector.spawn import DistributedThreads, DistributedProcess, Worker\nimport random\nimport time\nimport queue\nimport threading\nimport multiprocessing\n\ndef wait_on_b(b):\n    time.sleep(random.random())\n    # b will never complete because it is waiting on a.\n    print('working on b=%s' % b)\n    return 'working on b=%s' % b\n    # return 5\n\n\ndef wait_on_a(a):\n    time.sleep(1)\n    # a will never complete because it is waiting on b.\n    return 'working on a=%s' % a\n    # return 6\n\n# example data\npoll = [\n    {'id': 1, 'x': 'Nguyen'},\n    {'id': 1, 'x': 'Minh'},\n    {'id': 1, 'x': 'Tuan'},\n    {'id': 2, 'x': 'Vu'},\n    {'id': 3, 'x': 'Ai do khac'},\n    {'id': 2, 'x': 'Kim'},\n    {'id': 2, 'x': 'Oanh'},\n    {'id': 4, 'x': '1'},\n    {'id': 4, 'x': '2'},\n    {'id': 4, 'x': '3'},\n    {'id': 4, 'x': '4'},\n    {'id': 4, 'x': '5'},\n    {'id': 4, 'x': '6'},\n    {'id': 4, 'x': '7'},\n    {'id': 4, 'x': '8'},\n    {'id': 5, 'x': '101'},\n    {'id': 5, 'x': '102'},\n    {'id': 5, 'x': '103'},\n    {'id': 5, 'x': '104'},\n    {'id': 5, 'x': '105'},\n    {'id': 6, 'x': 'Test watching'},\n    {'id': 6, 'x': 'Test watching'},\n    {'id': 7, 'x': 'Test watching'},\n    {'id': 8, 'x': 'Test watching'},\n    {'id': 9, 'x': 'Test watching'},\n    {'id': 10, 'x': 'Test watching'},\n    {'id': 11, 'x': 'Test watching'},\n    {'id': 12, 'x': 'Test watching'},\n    {'id': 13, 'x': 'Test watching'},\n    {'id': 14, 'x': 'Test watching'},\n    {'id': 15, 'x': 'Test watching'},\n    {'id': 16, 'x': 'Test watching'},\n    {'id': 17, 'x': 'Test watching'},\n    {'id': 18, 'x': 'Test watching'},\n    {'id': 19, 'x': 'Test watching'},\n    {'id': 20, 'x': 'Test watching'},\n    {'id': 21, 'x': 'Test watching'},\n    {'id': 22, 'x': 'Test watching'},\n]\ndef main():\n    start = time.time()\n\n    thread_out_queue = queue.Queue()\n    pool = DistributedThreads(\n        max_workers=4, max_watching=100, out_queue=thread_out_queue)\n    for item in poll:\n        pool.submit_id(item['id'], wait_on_a, item)\n    t = Worker(thread_out_queue, print)\n    t.daemon = True\n    t.start()\n    pool.shutdown()\n    print('Finish after: ', time.time()-start, 'seconds')\n\n    print(\"========= End of threads ==============\")\n\n    process_out_queue = multiprocessing.Queue()\n    pool2 = DistributedProcess(\n        max_workers=4, max_watching=100, out_queue=process_out_queue)\n    for item in poll:\n        pool2.submit_id(item['id'], wait_on_b, item)\n    pool2.shutdown()\n\n    print('Finish after: ', time.time()-start, 'seconds')\n\n\nif __name__ == '__main__':\n    main()\n```\n\nAs the result, all name and number will same id will print in the exact order. Max watching should not be lesser than 100. If you put key/id to None or use submit instead of submit_id, it will do no order but faster.\n\nA Detail User Guide will comming soon...\n## Pros vs Cons and question\nFrom my opinion only, Microservice connector has the following Pros and Cons to improve\n### Pros:\n* Ease of use, Ease of development, you don't need to touch on http connection\n* Can build decentralize or Distributed system with Infinite scalability\n* Send and receive data with many types as string, int, float, list, dict.\n* Connect all around the world with internet\n\n### Cons:\n* Do not support send/receive tuple and set type (because I don't like them).\n* Do not support send/receive a whole class, return of decorator and server-side computer\n* Is not really fast log-broker server as RabbitMQ, ZeroMQ, kafka: *yes, oneService cannot send 10 million message per second like them, but it has other advance.*\n* Do not support Database, user/role management, system manager: *not yet, we are trying to write new feature include them. We welcome any contributor support us.*\n\n### Question:\n* Why not a load balancer ?\n\n\u003e *It is out of range. Load balancer cover the other layer. Other package can handle it better. But we consider to add a custom function for it.*\n\n* What about support more options, async/await ?\n\n\u003e *We are trying to connect by Sanic and Japronto soon*\n\n* What about data integrity, blockchain, token ?\n\n\u003e *We are trying to add them, but cannot be soon*\n\n## Authors\n\n* **Tuan Nguyen Minh** - *Financer and Developer* - email: ntuan221@gmail.com\n\nThank for the frameworks and their authors:\n* flask - micro webframework\n* Sanic - Gotta go fast\n* requests\n\nFavourite idioms:\n* Don't repeat your self\n* Think like human, make for human\n* Simple is stronger\n## License: BDS license","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminhtuan221%2Fmicroservices-connector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminhtuan221%2Fmicroservices-connector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminhtuan221%2Fmicroservices-connector/lists"}