Skip to content

Commit cfe0dc5

Browse files
committed
feat: v3.0.1.2. custom response json data structure is supported
1 parent f73eecb commit cfe0dc5

18 files changed

+639
-70
lines changed

Diff for: CHANGELOG

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# 变更
22

3+
#### v3.0.1.2
4+
feat: custome response format are supported.
5+
fix: test case with hive, ODPS and spark.
6+
docs: sync/async request
7+
38
#### v3.0.1.0 变更
49
feat: 支持多机license
510
refactor: 测试用例整理

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ The SLB binding succeeded, Access path http://somehost:someport,
8585
- [安装](docs/cn/install.md)
8686
- 服务能力
8787
- [服务与API](docs/cn/service.md)
88+
- [同步与异步请求](docs/cn/task.md)
8889
- 数据处理能力
8990
- [操作rds/hive/odps数据](docs/cn/dbm.md)
9091
- [spark处理数据](docs/cn/service.md)
@@ -109,6 +110,7 @@ The SLB binding succeeded, Access path http://somehost:someport,
109110
- [插件机制](docs/cn/plugin.md)
110111
- 最佳实践
111112
- [如何创建新项目](docs/cn/new-project.md)
113+
- [定制响应结构](docs/cn/custom-response-format.md)
112114
- [最佳实践](docs/cn/best-practice.md)
113115

114116
## 视频专区

Diff for: docs/cn/abt.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ABT 使用示例
22

3-
## 简易部署脚本使用方法
3+
## 简易部署脚本使用方法(不支持license)
44

55
使用前提:按照`ABT 参考`章节,完成配置`全局配置``项目配置`。不用怕,事实上你需要改写的配置非常少。
66

Diff for: docs/cn/custom-response-format.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# 定制响应结构
2+
3+
有时,你需要定制请求返回值的数据结构,目前已支持返回自定义的json格式,示例如下
4+
5+
```
6+
from ab import jsonify
7+
8+
9+
@algorithm()
10+
def custom_response():
11+
return jsonify({"res": 1})
12+
```

Diff for: docs/cn/service.md

+1-51
Original file line numberDiff line numberDiff line change
@@ -143,55 +143,6 @@ response:
143143
}
144144
```
145145

146-
### GET /api/task
147-
获取异步算法任务列表
148-
149-
query string:
150-
* page: 第几页
151-
* size: 每页条数
152-
153-
response:
154-
```
155-
{
156-
"code": 0,
157-
"data": [{
158-
"code": 2, // 0:新建, 1:执行中,2:运行结束,-1:异常
159-
"task_id": "d97704ef0b704b54bb777de090531eef",
160-
"app_name": "algorithm-base-demo-app",
161-
"algorithm_name": "async_example",
162-
"status": "begin", // 算法状态
163-
"gmt_create": "2019-09-02 19:35:52.000",
164-
"gmt_modified": "2019-09-02 20:23:34.000"
165-
}
166-
]
167-
}
168-
```
169-
170-
171-
### GET /api/task/{task_id}/
172-
获取异步算法任务状态。比上述算法列表多了data/log字段
173-
174-
path variable:
175-
* task_id: 上面接口返回的异步task_id
176-
177-
response:
178-
```
179-
{
180-
"code": 2, // 0:新建, 1:执行中,2:运行结束,-1:异常
181-
"task_id": "d97704ef0b704b54bb777de090531eef",
182-
"app_name": "algorithm-base-demo-app",
183-
"algorithm_name": "async_example",
184-
"status": "begin", // 算法状态
185-
"data": {
186-
"sample_rate": 100, // 采样率
187-
"sample_count": 50, // 采样行数
188-
}, // 算法的返回值
189-
"spark_app_id": "xxx", // spark application id
190-
"log": "yyy", // spark及算法中print的log
191-
"gmt_create": "2019-09-02 19:35:52.000",
192-
"gmt_modified": "2019-09-02 20:23:34.000"
193-
}
194-
```
195146

196147
### DELETE /api/data_source/{data_source_id}/table/{table_name}/cache
197148
删除表的所有缓存
@@ -256,5 +207,4 @@ except Exception as e:
256207
更多信息,详见 [异常与错误处理](error.md)
257208

258209

259-
# 已知问题
260-
- 通过/api/task可以查看所有结束的任务,目前没有删除机制
210+

Diff for: docs/cn/task.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# 请求类型
2+
3+
## 同步请求
4+
5+
同步请求,请求后会一直阻塞等待返回结果,用于请求耗时较短的请求。
6+
7+
在请求参数中,加入如下参数即可, mode参数的默认值就是sync。
8+
```
9+
"mode"="sync"
10+
```
11+
12+
## 异步请求
13+
14+
异步请求,请求发出后,会立刻返回`taskId`, 随后根据`taskId` 查询请求状态,最终获得请求返回值。用于请求耗时长,非实时的任务,比如Hive,ODPS,Spark等。
15+
16+
在请求参数中,加入如下参数即可
17+
```
18+
"mode"="async"
19+
```
20+
21+
### GET /api/task
22+
获取异步算法任务列表
23+
24+
query string:
25+
* page: 第几页
26+
* size: 每页条数
27+
28+
response:
29+
```
30+
{
31+
"code": 0,
32+
"data": [{
33+
"code": 2, // 0:新建, 1:执行中,2:运行结束,-1:异常
34+
"task_id": "d97704ef0b704b54bb777de090531eef",
35+
"app_name": "algorithm-base-demo-app",
36+
"algorithm_name": "async_example",
37+
"status": "begin", // 算法状态
38+
"gmt_create": "2019-09-02 19:35:52.000",
39+
"gmt_modified": "2019-09-02 20:23:34.000"
40+
}
41+
]
42+
}
43+
```
44+
45+
46+
### GET /api/task/{task_id}/
47+
获取异步算法任务状态。比上述算法列表多了data/log字段。状态返回值`code`
48+
49+
```
50+
"code": 2, // 0:新建, 1:执行中,2:运行结束,-1:异常
51+
```
52+
53+
path variable:
54+
* task_id: 上面接口返回的异步task_id
55+
56+
response:
57+
```
58+
{
59+
"code": 2, // 0:新建, 1:执行中,2:运行结束,-1:异常
60+
"task_id": "d97704ef0b704b54bb777de090531eef",
61+
"app_name": "algorithm-base-demo-app",
62+
"algorithm_name": "async_example",
63+
"status": "begin", // 算法状态
64+
"data": {
65+
"sample_rate": 100, // 采样率
66+
"sample_count": 50, // 采样行数
67+
}, // 算法的返回值
68+
"spark_app_id": "xxx", // spark application id
69+
"log": "yyy", // spark及算法中print的log
70+
"gmt_create": "2019-09-02 19:35:52.000",
71+
"gmt_modified": "2019-09-02 20:23:34.000"
72+
}
73+
```
74+
75+
## 已知问题
76+
- 通过/api/task可以查看所有结束的任务, 没有被删除掉

Diff for: ext/license/license.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# only enc
77
def step1(input_line):
88
sout = [chr(ord(a) ^ ord(b)) for (a, b) in
9-
zip(input_line, cycle("your-key"))]
9+
zip(input_line, cycle("utf-8oZFSxbFXYpZ4mcX5FIwEXecsYbutf-8"))]
1010
return "".join(sout)
1111

1212

Diff for: src/ab/plugins/db/hive.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import sqlalchemy
2+
13
from sqlalchemy import MetaData, Table
24
from sqlalchemy.exc import NoSuchTableError
3-
from sqlalchemy import *
4-
from sqlalchemy.engine import create_engine
5-
from sqlalchemy.schema import *
65

76
import thrift.transport.TSocket
87

Diff for: src/ab/task/recorder.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212

1313
class TaskRecorder:
14-
# TODO Task status
14+
"""
15+
the status will be updated to database
16+
"""
1517
ERROR = -1
1618
INIT = 0
1719
RUNNING = 1

Diff for: src/ab/task/task.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import contextlib
21
import os
32
import time
43
import uuid
@@ -142,6 +141,7 @@ def run(self):
142141
self.lazy_init()
143142
'''2. run'''
144143
ret = self.run_algorithm()
144+
# fixme: throw errors when return by jsonify
145145
self.recorder.done(ret)
146146
return ret
147147
finally:

Diff for: src/ab/utils/serializer.py

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import sys
33
import pickle
44
from datetime import date, datetime
5+
from flask import Response
56

67
import numpy
78
import pandas as pd
@@ -13,6 +14,8 @@
1314

1415
class AlgorithmEncoder(json.JSONEncoder):
1516
def default(self, o):
17+
if isinstance(o, Response):
18+
return str(o.data)
1619
if isinstance(o, pd.DataFrame):
1720
return o.to_dict('records')
1821
if isinstance(o, pd.Series):

Diff for: tests/api/algorithms/args.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
from ab.utils import logger
22
from ab.utils.algorithm import algorithm
3+
from ab import jsonify
34

45

56
@algorithm('args')
6-
def get_data(task_id, data_source_id=None, table_name=None, data=None, table_info=None, recorder=None, cache_client=None,
7+
def get_data(task_id, data_source_id=None, table_name=None, data=None, table_info=None, recorder=None,
8+
cache_client=None,
79
dfs_client=None, eureka_client=None, qs_arg=None, f1=None, single_form_arg: int = None,
810
couple_form_args: int = None, the_file=None):
911
logger.info('get task_id:', task_id)
1012
return {'task_id': task_id, 'data_source_id': data_source_id, 'table_name': table_name, 'data': data,
1113
'table_info': table_info, 'recorder': str(recorder), 'cache_client': str(cache_client),
12-
'dfs_client': str(dfs_client), 'eureka_client': str(eureka_client), 'spark': None, # spark init is slow, disable it here
14+
'dfs_client': str(dfs_client), 'eureka_client': str(eureka_client), 'spark': None,
15+
# spark init is slow, disable it here
1316
'qs_arg': qs_arg, 'f1': f1, 'single_form_arg': single_form_arg, 'couple_form_args': couple_form_args,
1417
'the_file_context': the_file.read().decode('utf-8') if the_file else None,
1518
'the_filename': the_file.filename if the_file else None
@@ -19,3 +22,9 @@ def get_data(task_id, data_source_id=None, table_name=None, data=None, table_inf
1922
@algorithm()
2023
def fixture_overwrite(f2=None, f3=None):
2124
return f2, f3
25+
26+
27+
@algorithm()
28+
def custom_response():
29+
# return "hello"
30+
return jsonify({"res": 1})

Diff for: tests/api/algorithms/task.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# coding: utf-8
2+
3+
4+
from ab.utils.algorithm import algorithm
5+
6+
7+
@algorithm()
8+
def sync():
9+
return "hello-sync-task"
10+
11+
12+
@algorithm()
13+
def async_unlimit():
14+
import time
15+
time.sleep(2)
16+
return "hello-async-unlimit-task"
17+
18+
19+
@algorithm()
20+
def async_pool():
21+
import time
22+
time.sleep(2)
23+
return "hello-async-pool-task"

Diff for: tests/api/test_hive_ldap.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,19 @@
22

33
hive = {
44
"type": "hive",
5-
"host": ac.get_value("test_hive_host"),
6-
"port": ac.get_value("test_hive_port"),
7-
"username": ac.get_value("test_hive_username"),
8-
"password": ac.get_value("test_hive_password"),
9-
"db": ac.get_value("test_hive_db_zyq")
5+
"host": ac.get_value("test_docker_hive_host"),
6+
"port": ac.get_value("test_docker_hive_port"),
7+
"username": ac.get_value("test_docker_hive_username"),
8+
"password": ac.get_value("test_docker_hive_password"),
9+
"db": ac.get_value("test_docker_hive_db_testdb")
1010
}
1111

12-
1312
def test_hive_ldap(client):
1413
input = {
1514
'data_source': hive,
1615
'cacheable': False,
1716
'args': {
18-
'table_name': 't'
17+
'table_name': 'student'
1918
}
2019
}
2120
resp = client.post_data('/api/algorithm/args?qs_arg=123', input)

0 commit comments

Comments
 (0)