Skip to content

Commit

Permalink
[Feature][Dubbo-python] Implement the basic functions of an RPC frame…
Browse files Browse the repository at this point in the history
…work. (#34)

* feat: do something about service reference

* fix: fix ci

* feat: define UnaryUnaryMultiCallable

* feat: update applicationConfig

* feat: do some work related to service reference

* feat: add ci

* fix: fix ci

* fix: fix ci

* feat: add logger feat

* fix: fix ci

* perf: Extension Manager becomes a singleton

* fix: fix ci

* refactor: Make the code more standardized and robust

* feat: add logger extension

* feat: add url

* fix: fix ci

* feat: finish logger part

* perf: update something about logger

* style: Becoming more regulated

* fix: fix ci

* fix: fix ci

* feat: update something about client

* fix: fix ci

* fix: Delete some invalid files

* feat: Complete the network transmission part

* perf: Optimization of the network transmission part

* feat: Complete the client's call link

* feat: Complete the basic functions of the client

* feat: Refactored and refined rpc calling capabilities

* docs: Comment completely using reStructuredText style

* fix: update something

* fix: fix ci
  • Loading branch information
cnzakii authored Aug 7, 2024
1 parent 4fd4b33 commit f3e45fa
Show file tree
Hide file tree
Showing 91 changed files with 9,675 additions and 1 deletion.
7 changes: 6 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ ignore =
max-line-length = 120

exclude =
.idea,
.git,
__pycache__,
docs

per-file-ignores =
__init__.py:F401
__init__.py:F401
# module level import not at top of file
dubbo/_imports.py:F401
# module level import not at top of file
dubbo/common/extension/logger_extension.py:E402
22 changes: 22 additions & 0 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Run Unittests

on: [push, pull_request]

jobs:
unittest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install dependencies
run: |
pip install -r requirements.txt
- name: Run unittests
run: |
python -m unittest discover -s tests -p 'test_*.py'
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ header: # `header` section is configurations for source codes license header.
- '.gitignore'
- '.github'
- '.flake8'
- 'requirements.txt'
comment: on-failure # on what condition license-eye will comment on the pull request, `on-failure`, `always`, `never`.

# license-location-threshold specifies the index threshold where the license header can be located,
Expand Down
15 changes: 15 additions & 0 deletions dubbo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
119 changes: 119 additions & 0 deletions dubbo/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional

from dubbo.common import constants as common_constants
from dubbo.common.types import DeserializingFunction, SerializingFunction
from dubbo.config import ReferenceConfig
from dubbo.proxy import RpcCallable
from dubbo.proxy.callables import MultipleRpcCallable


class Client:

__slots__ = ["_reference"]

def __init__(self, reference: ReferenceConfig):
self._reference = reference

def unary(
self,
method_name: str,
request_serializer: Optional[SerializingFunction] = None,
response_deserializer: Optional[DeserializingFunction] = None,
) -> RpcCallable:
return self._callable(
common_constants.UNARY_CALL_VALUE,
method_name,
request_serializer,
response_deserializer,
)

def client_stream(
self,
method_name: str,
request_serializer: Optional[SerializingFunction] = None,
response_deserializer: Optional[DeserializingFunction] = None,
) -> RpcCallable:
return self._callable(
common_constants.CLIENT_STREAM_CALL_VALUE,
method_name,
request_serializer,
response_deserializer,
)

def server_stream(
self,
method_name: str,
request_serializer: Optional[SerializingFunction] = None,
response_deserializer: Optional[DeserializingFunction] = None,
) -> RpcCallable:
return self._callable(
common_constants.SERVER_STREAM_CALL_VALUE,
method_name,
request_serializer,
response_deserializer,
)

def bidi_stream(
self,
method_name: str,
request_serializer: Optional[SerializingFunction] = None,
response_deserializer: Optional[DeserializingFunction] = None,
) -> RpcCallable:
return self._callable(
common_constants.BI_STREAM_CALL_VALUE,
method_name,
request_serializer,
response_deserializer,
)

def _callable(
self,
call_type: str,
method_name: str,
request_serializer: Optional[SerializingFunction] = None,
response_deserializer: Optional[DeserializingFunction] = None,
) -> RpcCallable:
"""
Generate a proxy for the given method
:param call_type: The call type.
:type call_type: str
:param method_name: The method name.
:type method_name: str
:param request_serializer: The request serializer.
:type request_serializer: Optional[SerializingFunction]
:param response_deserializer: The response deserializer.
:type response_deserializer: Optional[DeserializingFunction]
:return: The proxy.
:rtype: RpcCallable
"""
# get invoker
invoker = self._reference.get_invoker()
url = invoker.get_url()

# clone url
url = url.copy()
url.parameters[common_constants.METHOD_KEY] = method_name
url.parameters[common_constants.CALL_KEY] = call_type

# set serializer and deserializer
url.attributes[common_constants.SERIALIZER_KEY] = request_serializer
url.attributes[common_constants.DESERIALIZER_KEY] = response_deserializer

# create proxy
return MultipleRpcCallable(invoker, url)
32 changes: 32 additions & 0 deletions dubbo/common/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .classes import SingletonBase
from .deliverers import MultiMessageDeliverer, SingleMessageDeliverer
from .node import Node
from .types import DeserializingFunction, SerializingFunction
from .url import URL, create_url

__all__ = [
"SingleMessageDeliverer",
"MultiMessageDeliverer",
"URL",
"create_url",
"Node",
"SingletonBase",
"DeserializingFunction",
"SerializingFunction",
]
41 changes: 41 additions & 0 deletions dubbo/common/classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import threading

__all__ = ["SingletonBase"]


class SingletonBase:
"""
Singleton base class. This class ensures that only one instance of a derived class exists.
This implementation is thread-safe.
"""

_instance = None
_instance_lock = threading.Lock()

def __new__(cls, *args, **kwargs):
"""
Create a new instance of the class if it does not exist.
"""
if cls._instance is None:
with cls._instance_lock:
# double check
if cls._instance is None:
cls._instance = super(SingletonBase, cls).__new__(cls)
return cls._instance
62 changes: 62 additions & 0 deletions dubbo/common/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

PROTOCOL_KEY = "protocol"
TRIPLE = "triple"
TRIPLE_SHORT = "tri"

SIDE_KEY = "side"
SERVER_VALUE = "server"
CLIENT_VALUE = "client"

METHOD_KEY = "method"
SERVICE_KEY = "service"

SERVICE_HANDLER_KEY = "service-handler"

GROUP_KEY = "group"

LOCAL_HOST_KEY = "localhost"
LOCAL_HOST_VALUE = "127.0.0.1"
DEFAULT_PORT = 50051

SSL_ENABLED_KEY = "ssl-enabled"

SERIALIZATION_KEY = "serialization"
SERIALIZER_KEY = "serializer"
DESERIALIZER_KEY = "deserializer"


COMPRESSION_KEY = "compression"
COMPRESSOR_KEY = "compressor"
DECOMPRESSOR_KEY = "decompressor"


TRANSPORTER_KEY = "transporter"
TRANSPORTER_DEFAULT_VALUE = "aio"

TRUE_VALUE = "true"
FALSE_VALUE = "false"

CALL_KEY = "call"
UNARY_CALL_VALUE = "unary"
CLIENT_STREAM_CALL_VALUE = "client-stream"
SERVER_STREAM_CALL_VALUE = "server-stream"
BI_STREAM_CALL_VALUE = "bi-stream"

PATH_SEPARATOR = "/"
PROTOCOL_SEPARATOR = "://"
DYNAMIC_KEY = "dynamic"
Loading

0 comments on commit f3e45fa

Please sign in to comment.