Skip to content

Commit a26c833

Browse files
committed
feat: add workflow template id for pfop
1 parent 2c9c165 commit a26c833

File tree

5 files changed

+128
-39
lines changed

5 files changed

+128
-39
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pip-log.txt
3636
.coverage
3737
.tox
3838
nosetests.xml
39+
coverage.xml
3940

4041
# Translations
4142
*.mo
@@ -45,4 +46,4 @@ nosetests.xml
4546
.project
4647
.pydevproject
4748
/.idea
48-
/.venv
49+
/.venv*

qiniu/auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
str('fsizeMin'), # 上传文件最少字节数
3535
str('keylimit'), # 设置允许上传的key列表,字符串数组类型,数组长度不可超过20个,如果设置了这个字段,上传时必须提供key
3636

37-
str('persistentOps'), # 持久化处理操作
37+
str('persistentOps'), # 持久化处理操作,与 persistentWorkflowTemplateID 二选一
3838
str('persistentNotifyUrl'), # 持久化处理结果通知URL
3939
str('persistentPipeline'), # 持久化处理独享队列
4040
str('persistentType'), # 为 `1` 时,开启闲时任务,必须是 int 类型
41+
str('persistentWorkflowTemplateID'), # 工作流模板 ID,与 persistentOps 二选一
4142

4243
str('deleteAfterDays'), # 文件多少天后自动删除
4344
str('fileType'), # 文件的存储类型,0为标准存储,1为低频存储,2为归档存储,3为深度归档存储,4为归档直读存储

qiniu/services/processing/pfop.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,47 @@ def __init__(self, auth, bucket, pipeline=None, notify_url=None):
2424
self.pipeline = pipeline
2525
self.notify_url = notify_url
2626

27-
def execute(self, key, fops, force=None, persistent_type=None):
27+
def execute(self, key, fops=None, force=None, persistent_type=None, workflow_template_id=None):
2828
"""
2929
执行持久化处理
3030
3131
Parameters
3232
----------
3333
key: str
3434
待处理的源文件
35-
fops: list[str]
35+
fops: list[str], optional
3636
处理详细操作,规格详见 https://developer.qiniu.com/dora/manual/1291/persistent-data-processing-pfop
37+
与 template_id 二选一
3738
force: int or str, optional
3839
强制执行持久化处理开关
3940
persistent_type: int or str, optional
4041
持久化处理类型,为 '1' 时开启闲时任务
42+
template_id: str, optional
43+
与 fops 二选一
4144
Returns
4245
-------
4346
ret: dict
4447
持久化处理的 persistentId,类似 {"persistentId": 5476bedf7823de4068253bae};
4548
resp: ResponseInfo
4649
"""
47-
ops = ';'.join(fops)
48-
data = {'bucket': self.bucket, 'key': key, 'fops': ops}
50+
if not fops and not workflow_template_id:
51+
raise ValueError('Must provide one of fops or template_id')
52+
data = {
53+
'bucket': self.bucket,
54+
'key': key,
55+
}
4956
if self.pipeline:
5057
data['pipeline'] = self.pipeline
5158
if self.notify_url:
5259
data['notifyURL'] = self.notify_url
60+
if fops:
61+
data['fops'] = ';'.join(fops)
5362
if force == 1 or force == '1':
5463
data['force'] = str(force)
5564
if persistent_type and type(int(persistent_type)) is int:
5665
data['type'] = str(persistent_type)
66+
if workflow_template_id:
67+
data['workflowTemplateID'] = workflow_template_id
5768

5869
url = '{0}/pfop'.format(config.get_default('default_api_host'))
5970
return http._post_with_auth(url, data, self.auth)
Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import pytest
22

3-
43
from qiniu import PersistentFop, op_save
54

65

@@ -16,6 +15,7 @@ def test_pfop_execute(self, qn_auth):
1615
]
1716
ret, resp = pfop.execute('sintel_trailer.mp4', ops, 1)
1817
assert resp.status_code == 200, resp
18+
assert ret is not None, resp
1919
assert ret['persistentId'] is not None, resp
2020
global persistent_id
2121
persistent_id = ret['persistentId']
@@ -27,23 +27,71 @@ def test_pfop_get_status(self, qn_auth):
2727
assert resp.status_code == 200, resp
2828
assert ret is not None, resp
2929

30-
def test_pfop_idle_time_task(self, set_conf_default, qn_auth):
31-
persistence_key = 'python-sdk-pfop-test/test-pfop-by-api'
30+
@pytest.mark.parametrize(
31+
'persistent_options',
32+
(
33+
# included by above test_pfop_execute
34+
# {
35+
# 'persistent_type': None,
36+
# },
37+
{
38+
'persistent_type': 0,
39+
},
40+
{
41+
'persistent_type': 1,
42+
},
43+
{
44+
'workflow_template_id': 'test-workflow',
45+
},
46+
)
47+
)
48+
def test_pfop_idle_time_task(
49+
self,
50+
set_conf_default,
51+
qn_auth,
52+
bucket_name,
53+
persistent_options,
54+
):
55+
persistent_type = persistent_options.get('persistent_type')
56+
workflow_template_id = persistent_options.get('workflow_template_id', None)
57+
58+
execute_opts = {}
59+
if workflow_template_id:
60+
execute_opts['workflow_template_id'] = workflow_template_id
61+
else:
62+
persistent_key = '_'.join([
63+
'test-pfop/test-pfop-by-api',
64+
'type',
65+
str(persistent_type)
66+
])
67+
execute_opts['fops'] = [
68+
op_save(
69+
op='avinfo',
70+
bucket=bucket_name,
71+
key=persistent_key
72+
)
73+
]
74+
75+
if persistent_type is not None:
76+
execute_opts['persistent_type'] = persistent_type
77+
78+
pfop = PersistentFop(qn_auth, bucket_name)
79+
key = 'qiniu.png'
80+
ret, resp = pfop.execute(
81+
key,
82+
**execute_opts
83+
)
3284

33-
key = 'sintel_trailer.mp4'
34-
pfop = PersistentFop(qn_auth, 'testres')
35-
ops = [
36-
op_save(
37-
op='avthumb/m3u8/segtime/10/vcodec/libx264/s/320x240',
38-
bucket='pythonsdk',
39-
key=persistence_key
40-
)
41-
]
42-
ret, resp = pfop.execute(key, ops, force=1, persistent_type=1)
4385
assert resp.status_code == 200, resp
86+
assert ret is not None
4487
assert 'persistentId' in ret, resp
4588

4689
ret, resp = pfop.get_status(ret['persistentId'])
4790
assert resp.status_code == 200, resp
48-
assert ret['type'] == 1, resp
91+
assert ret is not None
4992
assert ret['creationDate'] is not None, resp
93+
94+
if persistent_id == 1:
95+
assert ret['type'] == 1, resp
96+
elif workflow_template_id:
97+
assert workflow_template_id in ret['taskFrom'], resp

tests/cases/test_services/test_storage/test_upload_pfop.py

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,60 @@
1212
# or this test will continue to occupy bucket space.
1313
class TestPersistentFopByUpload:
1414
@pytest.mark.parametrize('temp_file', [10 * MB], indirect=True)
15-
@pytest.mark.parametrize('persistent_type', [None, 0, 1])
15+
@pytest.mark.parametrize(
16+
'persistent_options',
17+
(
18+
{
19+
'persistent_type': None,
20+
},
21+
{
22+
'persistent_type': 0,
23+
},
24+
{
25+
'persistent_type': 1,
26+
},
27+
{
28+
'persistent_workflow_template_id': 'test-workflow',
29+
},
30+
)
31+
)
1632
def test_pfop_with_upload(
1733
self,
1834
set_conf_default,
1935
qn_auth,
2036
bucket_name,
2137
temp_file,
22-
persistent_type
38+
persistent_options,
2339
):
24-
key = 'test-pfop-upload-file'
25-
persistent_key = '_'.join([
26-
'test-pfop-by-upload',
27-
'type',
28-
str(persistent_type)
29-
])
30-
persistent_ops = ';'.join([
31-
qiniu.op_save(
32-
op='avthumb/m3u8/segtime/10/vcodec/libx264/s/320x240',
33-
bucket=bucket_name,
34-
key=persistent_key
35-
)
36-
])
40+
key = 'test-pfop/upload-file'
41+
persistent_type = persistent_options.get('persistent_type')
42+
persistent_workflow_template_id = persistent_options.get('persistent_workflow_template_id')
43+
44+
upload_policy = {}
3745

38-
upload_policy = {
39-
'persistentOps': persistent_ops
40-
}
46+
# set pfops or tmplate id
47+
if persistent_workflow_template_id:
48+
upload_policy['persistentWorkflowTemplateID'] = persistent_workflow_template_id
49+
else:
50+
persistent_key = '_'.join([
51+
'test-pfop/test-pfop-by-upload',
52+
'type',
53+
str(persistent_type)
54+
])
55+
persistent_ops = ';'.join([
56+
qiniu.op_save(
57+
op='avinfo',
58+
bucket=bucket_name,
59+
key=persistent_key
60+
)
61+
])
62+
upload_policy['persistentOps'] = persistent_ops
4163

64+
# set persistent type
4265
if persistent_type is not None:
4366
upload_policy['persistentType'] = persistent_type
4467

68+
# upload
4569
token = qn_auth.upload_token(
4670
bucket_name,
4771
key,
@@ -61,6 +85,10 @@ def test_pfop_with_upload(
6185
pfop = qiniu.PersistentFop(qn_auth, bucket_name)
6286
ret, resp = pfop.get_status(ret['persistentId'])
6387
assert resp.status_code == 200, resp
88+
assert ret is not None, resp
89+
assert ret['creationDate'] is not None, resp
90+
6491
if persistent_type == 1:
6592
assert ret['type'] == 1, resp
66-
assert ret['creationDate'] is not None, resp
93+
elif persistent_workflow_template_id:
94+
assert persistent_workflow_template_id in ret['taskFrom'], resp

0 commit comments

Comments
 (0)