Skip to content

Commit 55a5b80

Browse files
authored
Merge pull request #422 from FederatedAI/develop-1.11.0
Develop 1.11.0
2 parents 7452a51 + 5fe8a1f commit 55a5b80

File tree

19 files changed

+353
-143
lines changed

19 files changed

+353
-143
lines changed

RELEASE.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# Release 1.11.0
2+
## Major Features and Improvements
3+
* Add data table preview query interface
4+
5+
## Bug Fixes
6+
* Fix the performance problems of upload and reader in processing large amounts of data
7+
* Fix online inference cannot be done after model migration bug
8+
* Fix the model cannot be saved to the specified database bug
9+
* Fix reader data preview display bug
10+
11+
112
# Release 1.10.1
213
## Major Features and Improvements
314
* Optimize table info API

doc/swagger/swagger.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,57 @@ paths:
732732
type: string
733733
example: no find table
734734

735+
'/table/preview':
736+
post:
737+
summary: table data preview
738+
tags:
739+
- table
740+
requestBody:
741+
required: true
742+
content:
743+
application/json:
744+
schema:
745+
type: object
746+
required:
747+
- name
748+
- namespace
749+
properties:
750+
name:
751+
type: string
752+
example: "guest"
753+
namespace:
754+
type: string
755+
example: "data"
756+
responses:
757+
'200':
758+
description: get preview table success
759+
content:
760+
application/json:
761+
schema:
762+
type: object
763+
properties:
764+
retcode:
765+
type: integer
766+
example: 0
767+
retmsg:
768+
type: string
769+
example: success
770+
data:
771+
type: object
772+
'404':
773+
description: no found table
774+
content:
775+
application/json:
776+
schema:
777+
type: object
778+
properties:
779+
retcode:
780+
type: integer
781+
example: 210
782+
retmsg:
783+
type: string
784+
example: no find table
785+
735786
'/job/submit':
736787
post:
737788
summary: submit job

python/fate_flow/apps/job_app.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,11 @@ def update_job():
153153

154154
@manager.route('/report', methods=['POST'])
155155
def job_report():
156+
jobs = JobSaver.query_job(**request.json)
156157
tasks = JobSaver.query_task(**request.json)
157-
if not tasks:
158+
if not tasks or not jobs:
158159
return get_json_result(retcode=101, retmsg='find task failed')
159-
return get_json_result(retcode=0, retmsg='success', data=job_utils.task_report(tasks))
160+
return get_json_result(retcode=0, retmsg='success', data=job_utils.task_report(jobs, tasks))
160161

161162

162163
@manager.route('/parameter/update', methods=['POST'])

python/fate_flow/apps/model_app.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,12 @@ def query_model():
643643
return get_json_result(retcode=retcode, retmsg=retmsg, data=data)
644644

645645

646+
@manager.route('/query/detail', methods=['POST'])
647+
def query_model_detail():
648+
retcode, retmsg, data = model_utils.query_model_detail(**request.json)
649+
return get_json_result(retcode=retcode, retmsg=retmsg, data=data)
650+
651+
646652
@manager.route('/deploy', methods=['POST'])
647653
@validate_request('model_id', 'model_version')
648654
def deploy():

python/fate_flow/apps/table_app.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ def table_download():
158158
)
159159

160160

161+
@manager.route('/preview', methods=['post'])
162+
def table_data_preview():
163+
request_data = request.json
164+
from fate_flow.component_env_utils.env_utils import import_component_output_depend
165+
import_component_output_depend()
166+
data_table_meta = storage.StorageTableMeta(name=request_data.get("name"), namespace=request_data.get("namespace"))
167+
if not data_table_meta:
168+
return error_response(response_code=210, retmsg=f'no found table:{request_data.get("namespace")}, {request_data.get("name")}')
169+
170+
data = TableStorage.read_table_data(data_table_meta, limit=request_data.get("limit"))
171+
return get_json_result(retcode=0, retmsg='success', data=data)
172+
173+
161174
@manager.route('/delete', methods=['post'])
162175
def table_delete():
163176
request_data = request.json

python/fate_flow/components/api_reader.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,14 @@ def upload_data(self):
192192
)
193193
upload_registry_info = self.service_info.get("upload")
194194
logger.info(f"upload info:{upload_registry_info.to_dict()}")
195+
params = self.parameters.get("parameters", {})
196+
params.update({"job_id": self.tracker.job_id, })
197+
en_content = self.encrypt_content()
198+
if en_content:
199+
params.update({"sign": en_content})
195200
response = getattr(requests, upload_registry_info.f_method.lower(), None)(
196201
url=upload_registry_info.f_url,
197-
params={"requestBody": json.dumps(self.parameters.get("parameters", {}))},
202+
params={"requestBody": json.dumps(params)},
198203
data=data,
199204
headers={'Content-Type': data.content_type}
200205
)
@@ -206,3 +211,11 @@ def set_service_registry_info(self):
206211
if key == info.f_service_name:
207212
self.service_info[key] = info
208213
logger.info(f"set service registry info:{self.service_info}")
214+
215+
def encrypt_content(self, job_id=None):
216+
if not job_id:
217+
job_id = self.tracker.job_id
218+
import hashlib
219+
md5 = hashlib.md5()
220+
md5.update(job_id.encode())
221+
return md5.hexdigest()

python/fate_flow/components/reader.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from fate_flow.manager.data_manager import DataTableTracker, TableStorage, AnonymousGenerator
3636
from fate_flow.operation.job_tracker import Tracker
3737
from fate_flow.utils import data_utils
38+
from federatedml.feature.instance import Instance
3839

3940
LOGGER = log.getLogger()
4041
MAX_NUM = 10000
@@ -305,8 +306,22 @@ def data_info_display(output_table_meta):
305306
data_list[0].extend(headers)
306307
LOGGER.info(f"data info header: {data_list[0]}")
307308
for data in output_table_meta.get_part_of_data():
308-
delimiter = schema.get("meta", {}).get("delimiter") or output_table_meta.id_delimiter
309-
data_list.append(data[1].split(delimiter))
309+
if isinstance(data[1], str):
310+
delimiter = schema.get("meta", {}).get(
311+
"delimiter") or output_table_meta.id_delimiter
312+
data_list.append(data[1].split(delimiter))
313+
elif isinstance(data[1], Instance):
314+
table_data = []
315+
if data[1].inst_id:
316+
table_data = table_data.append(data[1].inst_id)
317+
if not data[1].label is None:
318+
table_data.append(data[1].label)
319+
320+
table_data.extend(data[1].features)
321+
data_list.append([str(v) for v in table_data])
322+
else:
323+
data_list.append(data[1])
324+
310325
data = np.array(data_list)
311326
Tdata = data.transpose()
312327
for data in Tdata:
@@ -317,7 +332,7 @@ def data_info_display(output_table_meta):
317332
if schema.get("label_name"):
318333
anonymous_info[schema.get("label_name")] = schema.get("anonymous_label")
319334
attribute_info[schema.get("label_name")] = "label"
320-
if schema.get("meta").get("id_list"):
335+
if schema.get("meta", {}).get("id_list"):
321336
for id_name in schema.get("meta").get("id_list"):
322337
if id_name in attribute_info:
323338
attribute_info[id_name] = "match_id"

python/fate_flow/components/upload.py

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -287,54 +287,59 @@ def get_count(input_file):
287287
count += 1
288288
return count
289289

290+
def kv_generator(self, input_feature_count, fp, job_id, part_of_data):
291+
fate_uuid = uuid.uuid1().hex
292+
get_line = self.get_line()
293+
line_index = 0
294+
LOGGER.info(input_feature_count)
295+
while True:
296+
lines = fp.readlines(JobDefaultConfig.upload_block_max_bytes)
297+
LOGGER.info(JobDefaultConfig.upload_block_max_bytes)
298+
if lines:
299+
for line in lines:
300+
values = line.rstrip().split(self.parameters["id_delimiter"])
301+
k, v = get_line(
302+
values=values,
303+
line_index=line_index,
304+
extend_sid=self.parameters["extend_sid"],
305+
auto_increasing_sid=self.parameters["auto_increasing_sid"],
306+
id_delimiter=self.parameters["id_delimiter"],
307+
fate_uuid=fate_uuid,
308+
)
309+
yield k, v
310+
line_index += 1
311+
if line_index <= 100:
312+
part_of_data.append((k, v))
313+
save_progress = line_index / input_feature_count * 100 // 1
314+
job_info = {
315+
"progress": save_progress,
316+
"job_id": job_id,
317+
"role": self.parameters["local"]["role"],
318+
"party_id": self.parameters["local"]["party_id"],
319+
}
320+
ControllerClient.update_job(job_info=job_info)
321+
else:
322+
return
323+
324+
def update_schema(self, head, fp):
325+
read_status = False
326+
if head is True:
327+
data_head = fp.readline()
328+
self.update_table_schema(data_head)
329+
read_status = True
330+
else:
331+
self.update_table_schema()
332+
return read_status
333+
290334
def upload_file(self, input_file, head, job_id=None, input_feature_count=None, table=None):
291335
if not table:
292336
table = self.table
293-
with open(input_file, "r") as fin:
294-
lines_count = 0
295-
if head is True:
296-
data_head = fin.readline()
337+
part_of_data = []
338+
with open(input_file, "r") as fp:
339+
if self.update_schema(head, fp):
297340
input_feature_count -= 1
298-
self.update_table_schema(data_head)
299-
else:
300-
self.update_table_schema()
301-
n = 0
302-
fate_uuid = uuid.uuid1().hex
303-
get_line = self.get_line()
304-
line_index = 0
305-
while True:
306-
data = list()
307-
lines = fin.readlines(JobDefaultConfig.upload_block_max_bytes)
308-
LOGGER.info(JobDefaultConfig.upload_block_max_bytes)
309-
if lines:
310-
# self.append_data_line(lines, data, n)
311-
for line in lines:
312-
values = line.rstrip().split(self.parameters["id_delimiter"])
313-
k, v = get_line(
314-
values=values,
315-
line_index=line_index,
316-
extend_sid=self.parameters["extend_sid"],
317-
auto_increasing_sid=self.parameters["auto_increasing_sid"],
318-
id_delimiter=self.parameters["id_delimiter"],
319-
fate_uuid=fate_uuid,
320-
)
321-
data.append((k, v))
322-
line_index += 1
323-
lines_count += len(data)
324-
save_progress = lines_count / input_feature_count * 100 // 1
325-
job_info = {
326-
"progress": save_progress,
327-
"job_id": job_id,
328-
"role": self.parameters["local"]["role"],
329-
"party_id": self.parameters["local"]["party_id"],
330-
}
331-
ControllerClient.update_job(job_info=job_info)
332-
table.put_all(data)
333-
if n == 0:
334-
table.meta.update_metas(part_of_data=data)
335-
else:
336-
return
337-
n += 1
341+
self.table.put_all(self.kv_generator(input_feature_count, fp, job_id, part_of_data))
342+
table.meta.update_metas(part_of_data=part_of_data)
338343

339344
def get_computing_table(self, name, namespace, schema=None):
340345
storage_table_meta = storage.StorageTableMeta(name=name, namespace=namespace)

python/fate_flow/db/service_registry.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,14 @@ def save(cls, service_config):
102102
cls.parameter_check(server_info)
103103
api_info = server_info.pop("api", {})
104104
for service_name, info in api_info.items():
105-
ServiceRegistry.save_service_info(server_name, service_name, uri=info.get('uri'), method=info.get('method', 'POST'), server_info=server_info)
105+
ServiceRegistry.save_service_info(
106+
server_name, service_name, uri=info.get('uri'),
107+
method=info.get('method', 'POST'),
108+
server_info=server_info,
109+
data=info.get("data", {}),
110+
headers=info.get("headers", {}),
111+
params=info.get("params", {})
112+
)
106113
cls.save_server_info_to_db(server_name, server_info.get("host"), server_info.get("port"), protocol="http")
107114
setattr(cls, server_name.upper(), server_info)
108115
return update_server

python/fate_flow/external/storage/mysql.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def save(self):
5959
self._con.commit()
6060
sql = None
6161
LOGGER.info(f"save data count:{count}")
62-
if count > 0:
62+
if count > 0 and sql:
6363
sql = ",".join(sql.split(",")[:-1]) + ";"
6464
self._cur.execute(sql)
6565
self._con.commit()

0 commit comments

Comments
 (0)