Skip to content

Commit 4a60a10

Browse files
authored
feat(interactive): Support customizing coordinator configuration for interactive (#4474)
Support specifying configuration for coordinator when deploy Interactive.
1 parent 89cd019 commit 4a60a10

File tree

6 files changed

+147
-28
lines changed

6 files changed

+147
-28
lines changed

.github/workflows/flex-interactive.yml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ jobs:
4141
python3 -m pip install --upgrade pip && python3 -m pip install click
4242
python3 ./gsctl.py flexbuild interactive --app docker
4343
44+
- name: Prepare dataset
45+
env:
46+
GS_TEST_DIR: /tmp/gstest
47+
run: |
48+
git clone -b master --single-branch --depth=1 https://github.com/GraphScope/gstest.git ${GS_TEST_DIR}
49+
4450
- name: Build gsctl Wheel Package
4551
run: |
4652
cd ${GITHUB_WORKSPACE}/python
@@ -49,6 +55,8 @@ jobs:
4955
python3 setup_flex.py bdist_wheel
5056
python3 setup_gsctl.py bdist_wheel
5157
58+
python3 -m pip install ${GITHUB_WORKSPACE}/python/dist/*.whl
59+
5260
- name: Setup tmate session
5361
uses: mxschmitt/action-tmate@v3
5462
if: false
@@ -59,10 +67,9 @@ jobs:
5967
COORDINATOR_PORT: 8080
6068
COORDINATOR_ENDPOINT: "http://127.0.0.1:8080"
6169
run: |
62-
# install gsctl
63-
python3 -m pip install ${GITHUB_WORKSPACE}/python/dist/*.whl
6470
# launch service: ${COORDINATOR_PORT} for coordinator http port; ${CYPHER_PORT} for cypher port;
65-
gsctl instance deploy --type interactive --image-registry graphscope --image-tag latest --cypher-port ${CYPHER_PORT} --coordinator-port ${COORDINATOR_PORT} --interactive-config ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml
71+
gsctl instance deploy --type interactive --image-registry graphscope --image-tag latest --cypher-port ${CYPHER_PORT} \
72+
--coordinator-port ${COORDINATOR_PORT} --config ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml
6673
sleep 20
6774
# test
6875
python3 -m pip install --no-cache-dir pytest pytest-cov pytest-timeout pytest-xdist
@@ -79,6 +86,33 @@ jobs:
7986
# destroy instance
8087
gsctl instance destroy --type interactive -y
8188
89+
- name: Test customizing coordinator config
90+
env:
91+
CYPHER_PORT: 7688
92+
COORDINATOR_PORT: 8080
93+
COORDINATOR_ENDPOINT: "http://127.0.0.1:8080"
94+
GS_TEST_DIR: /tmp/gstest
95+
run: |
96+
# launch service: ${COORDINATOR_PORT} for coordinator http port; ${CYPHER_PORT} for cypher port;
97+
cat >> ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml << EOF
98+
coordinator:
99+
max_content_length: 1048576 # 1MB
100+
EOF
101+
gsctl instance deploy --type interactive --image-registry graphscope --image-tag latest --cypher-port ${CYPHER_PORT} \
102+
--coordinator-port ${COORDINATOR_PORT} --config ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml \
103+
--admin-port 7778 --storedproc-port 10001
104+
sleep 20
105+
# test
106+
python3 -m pip install --no-cache-dir pytest pytest-cov pytest-timeout pytest-xdist
107+
python3 -m pytest -d --tx popen//python=python3 \
108+
-s -v \
109+
--cov=graphscope --cov-config=${GITHUB_WORKSPACE}/python/.coveragerc --cov-report=xml --cov-report=term \
110+
--exitfirst \
111+
$(dirname $(python3 -c "import graphscope.gsctl as gsctl; print(gsctl.__file__)"))/tests/test_file_uploading.py
112+
113+
# destroy instance
114+
gsctl instance destroy --type interactive -y
115+
82116
- name: Test basic examples
83117
run: |
84118
# build gs_interactive wheel package
@@ -87,7 +121,7 @@ jobs:
87121
cd python && pip3 install -r requirements.txt && python3 setup.py build_proto
88122
python3 setup.py bdist_wheel
89123
pip3 install dist/*.whl
90-
gsctl instance deploy --type interactive --image-registry graphscope --image-tag latest --interactive-config ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml
124+
gsctl instance deploy --type interactive --image-registry graphscope --image-tag latest --config ${GITHUB_WORKSPACE}/flex/tests/hqps/interactive_config_test.yaml
91125
sleep 20
92126
# test
93127
cd ${GITHUB_WORKSPACE}/flex/interactive/sdk/examples/python

docs/flex/interactive/configuration.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Below is a list of all configurable items:
1515
| admin-port | 7777 | The port of the interactive admin service | v0.3 |
1616
| storedproc-port | 10000 | The port of the interactive stored procedure service | v0.3 |
1717
| cypher-port | 7687 | The port of the cypher service | v0.3 |
18-
| config | None | The customized configuration file for engine interactive service | v0.4 |
18+
| config | None | The customized configuration file for engine interactive service | v0.4 |
1919
<!-- | gremlin-port | None | The port of the gremlin service | v0.3 | -->
2020

2121

@@ -50,7 +50,7 @@ By default, `Interactive` will initialize the service with its default settings.
5050
However, GraphScope Interactive is designed to be flexible and adaptable to your specific needs. This means you can tailor the service's behavior using custom configurations.
5151

5252

53-
#### Customizing Your Service Configuration
53+
#### Customizing Interactive Engine Service Configuration
5454
To customize the service's settings, you can provide a YAML configuration file `interactive_config.yaml`. This file allows you to specify various parameters, from directory paths to log levels, ensuring the service aligns with your requirements. To use a custom configuration, simply pass the YAML file to the command as follows:
5555

5656
```bash
@@ -61,6 +61,19 @@ gsctl instance deploy --type interactive --config ./interactive_config.yaml
6161
Please be aware that you're not required to configure every option. Simply adjust the settings that are relevant to your needs. Any options left unconfigured will automatically adopt their default values, as detailed in the following sections.
6262
```
6363

64+
#### Customize Coordinator Service Configuration
65+
66+
When deploying Interactive, a supplementary service called the Coordinator is also initiated. This service functions similarly to the `ApiServer` in Kubernetes, providing users with a consistent and standardized set of APIs to interact with the GraphScope platform.
67+
You could also customize the configuration for coordinator service, just put the configuration in `coordinator` section.
68+
69+
An example of a coordinator related configuration is as follows:
70+
71+
```yaml
72+
coordinator:
73+
max_content_length: 5242880 # maximum bytes of content the coordinator can handle
74+
```
75+
76+
For more details, consult [config.py](https://github.com/alibaba/GraphScope/blob/main/python/graphscope/config.py).
6477
6578
6679
##### Sample Configuration
@@ -121,6 +134,7 @@ In this following table, we use the `.` notation to represent the hierarchy with
121134
| compiler.planner.rules.NotMatchToAntiJoinRule | N/A | An optimization rule that transforms a "not exist" pattern into an anti-join operation | 0.0.1 |
122135
| compiler.query_timeout | 3000000 | The maximum time for compiler to wait engine's reply, in `ms` | 0.0.3 |
123136
| http_service.sharding_mode | exclusive | The sharding mode for http service, In exclusive mode, one shard is reserved exclusively for service admin request. In cooperative, both query request and admin request could be served by any shard. | 0.5 |
137+
| coordinator.max_content_length | 1073741824 | The maximum length of a http request that coordinator could handle | 0.5 |
124138

125139
#### TODOs
126140

flex/tests/hqps/interactive_config_test.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ http_service:
4141
default_listen_address: localhost
4242
admin_port: 7777
4343
query_port: 10000
44+
coordinator:
45+
max_content_length: 1048576 # 1MB

k8s/dockerfiles/interactive-entrypoint.sh

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ set -e
1818
DEFAULT_GRAPH_NAME=gs_interactive_default_graph
1919
BULK_LOADER_BINARY_PATH=/opt/flex/bin/bulk_loader
2020
INTERACTIVE_SERVER_BIN=/opt/flex/bin/interactive_server
21+
DEFAULT_INTERACTIVE_CONFIG_FILE=/opt/flex/share/interactive_config.yaml
2122

2223
function usage() {
2324
cat << EOF
@@ -54,7 +55,7 @@ function prepare_workspace() {
5455
fi
5556
# prepare interactive_config.yaml
5657
engine_config_path="${workspace}/conf/interactive_config.yaml"
57-
cp /opt/flex/share/interactive_config.yaml $engine_config_path
58+
cp ${DEFAULT_INTERACTIVE_CONFIG_FILE} $engine_config_path
5859
#make sure the line which start with default_graph is changed to default_graph: ${DEFAULT_GRAPH_NAME}
5960
sed -i "s/default_graph:.*/default_graph: ${DEFAULT_GRAPH_NAME}/" $engine_config_path
6061
# By default, we occupy the all available cpus
@@ -96,6 +97,10 @@ function launch_service() {
9697
}
9798

9899
function launch_coordinator() {
100+
if [ $# -ne 1 ]; then
101+
echo "Usage: launch_coordinator <port_mapping>"
102+
exit 1
103+
fi
99104
local host_ports=()
100105
local container_ports=()
101106
if [ -n "$1" ]; then
@@ -108,30 +113,34 @@ function launch_coordinator() {
108113
fi
109114
if $ENABLE_COORDINATOR;
110115
then
111-
coordinator_config_file="/tmp/coordinator-config.yaml"
112-
cat > $coordinator_config_file << EOF
113-
coordinator:
114-
http_port: 8080
115-
116-
launcher_type: hosts
117-
116+
dst_coordinator_config_file="/tmp/coordinator_config_$(date +%s).yaml"
117+
cat > $dst_coordinator_config_file << EOF
118118
session:
119119
instance_id: demo
120+
launcher_type: hosts
121+
coordinator:
122+
http_port: 8080
120123
EOF
124+
python3 -m pip install pyyaml
125+
res=$(python3 -c "import yaml; config = yaml.safe_load(open('${DEFAULT_INTERACTIVE_CONFIG_FILE}')); print(yaml.dump(config.get('coordinator', {}), default_flow_style=False, indent=4))")
126+
# for each line in res, echo to dst_coordinator_config_file with 2 spaces indentation
127+
while IFS= read -r line; do
128+
echo " $line" >> $dst_coordinator_config_file
129+
done <<< "$res"
121130

122131
if [ ${#host_ports[@]} -gt 0 ]; then
123-
echo "interactive:" >> $coordinator_config_file
124-
echo " port_mapping:" >> $coordinator_config_file
132+
echo "interactive:" >> $dst_coordinator_config_file
133+
echo " port_mapping:" >> $dst_coordinator_config_file
125134
for i in "${!host_ports[@]}"; do
126-
echo " ${container_ports[$i]}: ${host_ports[$i]}" >> $coordinator_config_file
135+
echo " ${container_ports[$i]}: ${host_ports[$i]}" >> $dst_coordinator_config_file
127136
done
128137
fi
129138
# i.e
130139
# interactive:
131140
# port_mapping:
132141
# 8080: 8081
133142
# 7777: 7778
134-
python3 -m gscoordinator --config-file $coordinator_config_file
143+
python3 -m gscoordinator --config-file $dst_coordinator_config_file
135144
fi
136145
}
137146

@@ -179,4 +188,5 @@ done
179188

180189
prepare_workspace $WORKSPACE
181190
launch_service $WORKSPACE
191+
# Note that the COORDINATOR_CONFIG_FILE should be inside the container
182192
launch_coordinator $PORT_MAPPING

python/graphscope/gsctl/commands/dev.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
# Interactive docker container config
4343
INTERACTIVE_DOCKER_CONTAINER_NAME = "gs-interactive-instance"
4444
INTERACTIVE_DOCKER_CONTAINER_LABEL = "flex=interactive"
45-
INTERACTIVE_DOCKER_DEFAULT_CONFIG_PATH = "/opt/flex/share/interactive_config.yaml"
45+
INTERACTIVE_DOCKER_DEFAULT_CONFIG_PATH = "/opt/flex/share/config.yaml"
46+
COORDINATOR_DOCKER_DEFAULT_CONFIG_PATH = "/opt/flex/share/coordinator_config.yaml"
4647

4748
scripts_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "scripts")
4849
install_deps_script = os.path.join(scripts_dir, "install_deps.sh")
@@ -191,7 +192,7 @@ def interactive(app, graphscope_repo, version):
191192
required=False,
192193
)
193194
@click.option(
194-
"--interactive-config",
195+
"--config",
195196
help="Interactive config file path [docker only]",
196197
required=False,
197198
default=None,
@@ -234,7 +235,7 @@ def deploy(
234235
storedproc_port,
235236
cypher_port,
236237
gremlin_port,
237-
interactive_config,
238+
config,
238239
): # noqa: F811
239240
"""Deploy a GraphScope Flex instance"""
240241
cmd = []
@@ -258,17 +259,15 @@ def deploy(
258259
]
259260
if gremlin_port != -1:
260261
cmd.extend(["-p", f"{gremlin_port}:8182"])
261-
if interactive_config is not None:
262-
if not os.path.isfile(interactive_config):
262+
if config is not None:
263+
if not os.path.isfile(config):
263264
click.secho(
264-
f"Interactive config file {interactive_config} does not exist.",
265+
f"Interactive config file {config} does not exist.",
265266
fg="red",
266267
)
267268
return
268-
interactive_config = os.path.abspath(interactive_config)
269-
cmd.extend(
270-
["-v", f"{interactive_config}:{INTERACTIVE_DOCKER_DEFAULT_CONFIG_PATH}"]
271-
)
269+
config = os.path.abspath(config)
270+
cmd.extend(["-v", f"{config}:{INTERACTIVE_DOCKER_DEFAULT_CONFIG_PATH}"])
272271
image = f"{image_registry}/{type}:{image_tag}"
273272
cmd.extend([image, "--enable-coordinator"])
274273
cmd.extend(
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright 2020 Alibaba Group Holding Limited. All Rights Reserved.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#
18+
19+
import os
20+
import warnings
21+
22+
# Disable warnings
23+
warnings.filterwarnings("ignore", category=Warning)
24+
25+
import time
26+
27+
import pytest
28+
29+
from graphscope.gsctl.impl import connect_coordinator
30+
from graphscope.gsctl.impl import disconnect_coordinator
31+
from graphscope.gsctl.impl import upload_file
32+
33+
COORDINATOR_ENDPOINT = "http://127.0.0.1:8080"
34+
35+
36+
class TestFileUploading(object):
37+
def setup_class(self):
38+
if "COORDINATOR_ENDPOINT" in os.environ:
39+
COORDINATOR_ENDPOINT = os.environ["COORDINATOR_ENDPOINT"]
40+
self.deployment_info = connect_coordinator(COORDINATOR_ENDPOINT)
41+
42+
def test_upload_file(self):
43+
"""
44+
This test assumes that coordinator.max_content_length is set to less than 2MB.
45+
"""
46+
gs_test_dir = os.environ.get("GS_TEST_DIR")
47+
if gs_test_dir is None:
48+
raise ValueError("GS_TEST_DIR is not set.")
49+
upload_file(gs_test_dir + "/modern_graph/person.csv")
50+
51+
with pytest.raises(Exception):
52+
upload_file(gs_test_dir + "/modern_graph/person_not_exist.csv")
53+
54+
with pytest.raises(Exception):
55+
upload_file(
56+
gs_test_dir + "/flex/ldbc-sf01-long-date/post_hasCreator_person_0_0.csv"
57+
)
58+
59+
def teardown_class(self):
60+
disconnect_coordinator()

0 commit comments

Comments
 (0)