Skip to content

Commit 3e471ef

Browse files
authored
feat: add support for pfop workflow template (#265)
1 parent b70f8f2 commit 3e471ef

File tree

7 files changed

+162
-40
lines changed

7 files changed

+162
-40
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
**2024-09-05**
22

3+
v8.7.0
4+
5+
新增:持久化处理,支持工作流模版
6+
37
v8.6.0
48

59
新增:验证 Qbox, Qiniu 签名的辅助方法

src/Qiniu/QiniuCSharpSDK.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ public class QiniuCSharpSDK
3737
/// <summary>
3838
/// SDK版本号
3939
/// </summary>
40-
public const string VERSION = "8.6.0";
40+
public const string VERSION = "8.7.0";
4141

4242
}

src/Qiniu/Storage/OperationManager.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,46 @@ public OperationManager(Mac mac, Config config)
3737
/// </summary>
3838
/// <param name="bucket">空间</param>
3939
/// <param name="key">空间文件的key</param>
40-
/// <param name="fops">操作(命令参数)</param>
40+
/// <param name="fops">操作(命令参数),与 workflowTemplateId 二选一</param>
4141
/// <param name="pipeline">私有队列</param>
4242
/// <param name="notifyUrl">通知url</param>
4343
/// <param name="force">forece参数</param>
44-
/// <param name="persistentType">为 1 时开启闲时任务</param>
44+
/// <param name="type">为 1 时开启闲时任务</param>
45+
/// <param name="workflowTemplateId">模版 ID,与 fops 二选一</param>
4546
/// <returns>pfop操作返回结果,正确返回结果包含persistentId</returns>
4647
public PfopResult Pfop(
4748
string bucket,
4849
string key,
49-
string fops,
50-
string pipeline,
51-
string notifyUrl,
52-
bool force,
53-
int type = 0
50+
string fops=null,
51+
string pipeline=null,
52+
string notifyUrl=null,
53+
bool force=false,
54+
int type = 0,
55+
string workflowTemplateId = null
5456
)
5557
{
5658
PfopResult result = new PfopResult();
5759

60+
if (string.IsNullOrEmpty(fops) && string.IsNullOrEmpty(workflowTemplateId))
61+
{
62+
throw new ArgumentException("Must provide one of fops or workflowTemplateId");
63+
}
64+
5865
try
5966
{
6067
string pfopUrl = string.Format("{0}/pfop/", this.config.ApiHost(this.mac.AccessKey, bucket));
6168

6269
StringBuilder sb = new StringBuilder();
63-
sb.AppendFormat("bucket={0}&key={1}&fops={2}", StringHelper.UrlEncode(bucket), StringHelper.UrlEncode(key),
64-
StringHelper.UrlEncode(fops));
70+
sb.AppendFormat("bucket={0}&key={1}", StringHelper.UrlEncode(bucket), StringHelper.UrlEncode(key));
71+
if (!string.IsNullOrEmpty(fops))
72+
{
73+
sb.AppendFormat("&fops={0}", StringHelper.UrlEncode(fops));
74+
}
75+
76+
if (!string.IsNullOrEmpty(workflowTemplateId))
77+
{
78+
sb.AppendFormat("&workflowTemplateID={0}", workflowTemplateId);
79+
}
6580
if (!string.IsNullOrEmpty(notifyUrl))
6681
{
6782
sb.AppendFormat("&notifyURL={0}", StringHelper.UrlEncode(notifyUrl));

src/Qiniu/Storage/PfopInfo.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ public class PfopInfo
5353
[JsonProperty("reqid")]
5454
public string Reqid;
5555
/// <summary>
56+
/// 任务来源
57+
/// </summary>
58+
[JsonProperty("taskFrom")]
59+
public string TaskFrom;
60+
/// <summary>
5661
/// 数据处理的命令集合
5762
/// </summary>
5863
[JsonProperty("items")]

src/Qiniu/Storage/PutPolicy.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public class PutPolicy
9494
public int? CallbackFetchKey { get; set; }
9595

9696
/// <summary>
97-
/// [可选]上传预转持久化
97+
/// [可选]上传预转持久化,与 PersistentWorkflowTemplateId 二选一
9898
/// </summary>
9999
[JsonProperty("persistentOps", NullValueHandling = NullValueHandling.Ignore)]
100100
public string PersistentOps { get; set; }
@@ -116,6 +116,12 @@ public class PutPolicy
116116
/// </summary>
117117
[JsonProperty("persistentType", NullValueHandling = NullValueHandling.Ignore)]
118118
public int? PersistentType { get; set; }
119+
120+
/// <summary>
121+
/// [可选]任务模版,与 PersistentOps 二选一
122+
/// </summary>
123+
[JsonProperty("persistentWorkflowTemplateID", NullValueHandling = NullValueHandling.Ignore)]
124+
public string PersistentWorkflowTemplateId { get; set; }
119125

120126

121127
/// <summary>

src/QiniuTests/Storage/FormUploaderTests.cs

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Qiniu.Http;
33
using System;
44
using System.Collections.Generic;
5+
using System.Text;
56
using Newtonsoft.Json;
67
using Qiniu.Util;
78
using Qiniu.Tests;
@@ -82,13 +83,14 @@ public void UploadFileV2Test()
8283
System.IO.File.Delete(filePath);
8384
}
8485

85-
[Test]
86-
public void UploadFileWithPersistTypeTest()
86+
[TestCaseSource(typeof(OperationManagerTests), nameof(OperationManagerTests.PfopOptionsTestCases))]
87+
public void UploadFileWithPersistOptionsTest(int type, string workflowId)
8788
{
8889
Mac mac = new Mac(AccessKey, SecretKey);
89-
Random rand = new Random();
90-
string key = string.Format("UploadFileTest_{0}.dat", rand.Next());
90+
string bucketName = Bucket;
91+
string key = "test-pfop/upload-file";
9192

93+
// generate file to upload
9294
string tempPath = System.IO.Path.GetTempPath();
9395
int rnd = new Random().Next(1, 100000);
9496
string filePath = tempPath + "resumeFile" + rnd.ToString();
@@ -99,37 +101,70 @@ public void UploadFileWithPersistTypeTest()
99101
sw.Close();
100102
stream.Close();
101103

104+
// generate put policy
102105
PutPolicy putPolicy = new PutPolicy();
103-
putPolicy.Scope = Bucket + ":" + key;
106+
putPolicy.Scope = string.Join(":", bucketName, key);
104107
putPolicy.SetExpires(3600);
105108
putPolicy.DeleteAfterDays = 1;
106-
string saveEntry = Base64.UrlSafeBase64Encode(Bucket + ":pfop-test_avinfo");
107-
putPolicy.PersistentOps = "avinfo|saveas/" + saveEntry;
108-
putPolicy.PersistentType = 1;
109-
string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
109+
110+
StringBuilder persistentKeyBuilder = new StringBuilder("test-pfop/test-pfop-by-upload");
111+
if (type > 0)
112+
{
113+
persistentKeyBuilder.Append("type_" + type);
114+
putPolicy.PersistentType = type;
115+
}
116+
117+
if (!string.IsNullOrEmpty(workflowId))
118+
{
119+
putPolicy.PersistentWorkflowTemplateId = workflowId;
120+
}
121+
else
122+
{
123+
string saveEntry = Base64.UrlSafeBase64Encode(String.Join(
124+
":",
125+
bucketName,
126+
persistentKeyBuilder.ToString()
127+
));
128+
putPolicy.PersistentOps = "avinfo|saveas/" + saveEntry;
129+
}
130+
131+
// upload
110132
Config config = new Config();
111-
config.Zone = Zone.ZONE_CN_East;
112133
config.UseHttps = true;
113134
config.UseCdnDomains = true;
114-
FormUploader target = new FormUploader(config);
115-
PutExtra extra = new PutExtra();
116-
extra.Version = "v2";
117-
HttpResult result = target.UploadFile(filePath, key, token, extra);
135+
string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
136+
FormUploader uploader = new FormUploader(config);
137+
HttpResult result = uploader.UploadFile(filePath, key, token, null);
118138
Console.WriteLine("form upload result: " + result.ToString());
119139
Assert.AreEqual((int)HttpCode.OK, result.Code);
120140
System.IO.File.Delete(filePath);
121141

142+
// get persist task info
122143
Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Text.ToString());
123144
Assert.IsTrue(dict.ContainsKey("persistentId"));
124145
OperationManager manager = new OperationManager(mac, config);
125146
PrefopResult prefopRet = manager.Prefop(dict["persistentId"].ToString());
147+
148+
// assert the result
126149
if (prefopRet.Code != (int)HttpCode.OK)
127150
{
128151
Assert.Fail("prefop error: " + prefopRet.ToString());
129152
}
130-
Assert.AreEqual(1, prefopRet.Result.Type);
153+
131154
Assert.IsNotNull(prefopRet.Result.CreationDate);
132155
Assert.IsNotEmpty(prefopRet.Result.CreationDate);
156+
157+
if (type == 1)
158+
{
159+
Assert.AreEqual(1, prefopRet.Result.Type);
160+
}
161+
162+
if (!string.IsNullOrEmpty(workflowId))
163+
{
164+
Assert.IsNotNull(prefopRet.Result.TaskFrom);
165+
Assert.IsNotEmpty(prefopRet.Result.TaskFrom);
166+
Assert.IsTrue(prefopRet.Result.TaskFrom.Contains(workflowId));
167+
}
133168
}
134169
}
135170
}

src/QiniuTests/Storage/OperationManagerTests.cs

Lines changed: 71 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
using NUnit.Framework;
22
using System;
3+
using System.Collections;
34
using System.Text;
45
using Qiniu.Util;
56
using Qiniu.Http;
6-
using Qiniu.Storage;
77
using Qiniu.Tests;
88

99
namespace Qiniu.Storage.Tests
1010
{
1111
[TestFixture]
12-
public class OperationManagerTests :TestEnv
12+
public class OperationManagerTests : TestEnv
1313
{
1414
private OperationManager getOperationManager()
1515
{
1616
Mac mac = new Mac(AccessKey, SecretKey);
1717
Config config = new Config();
18-
// config.UseHttps = true;
18+
config.UseHttps = true;
1919

2020
OperationManager manager = new OperationManager(mac, config);
2121
return manager;
@@ -50,31 +50,88 @@ public void PfopAndPrefopTest()
5050
Console.WriteLine(ret.ToString());
5151
}
5252

53-
[Test]
54-
public void PfopWithIdleTimeTest()
53+
public static IEnumerable PfopOptionsTestCases
5554
{
55+
get
56+
{
57+
yield return new TestCaseData(
58+
0, // type
59+
null // workflow template id
60+
);
61+
yield return new TestCaseData(
62+
1,
63+
null
64+
);
65+
yield return new TestCaseData(
66+
0,
67+
"test-workflow"
68+
);
69+
}
70+
}
71+
72+
[TestCaseSource(typeof(OperationManagerTests), nameof(PfopOptionsTestCases))]
73+
public void PfopWithOptionsTest(int type, string workflowId)
74+
{
75+
string bucketName = Bucket;
5676
string key = "qiniu.mp4";
57-
bool force = true;
58-
int type = 1;
59-
string pipeline = null;
60-
string saveJpgEntry = Base64.UrlSafeBase64Encode(Bucket + ":vframe_test_target.jpg");
61-
string vframeJpgFop = "vframe/jpg/offset/1|saveas/" + saveJpgEntry;
77+
78+
StringBuilder persistentKeyBuilder = new StringBuilder("test-pfop/test-pfop-by-api");
79+
if (type > 0)
80+
{
81+
persistentKeyBuilder.Append("type_" + type);
82+
}
83+
84+
string fops;
85+
if (!string.IsNullOrEmpty(workflowId))
86+
{
87+
fops = null;
88+
}
89+
else
90+
{
91+
string saveEntry = Base64.UrlSafeBase64Encode(String.Join(
92+
":",
93+
bucketName,
94+
persistentKeyBuilder.ToString()
95+
));
96+
fops = "avinfo|saveas/" + saveEntry;
97+
}
6298

6399
OperationManager manager = getOperationManager();
64-
PfopResult pfopRet = manager.Pfop(Bucket, key, vframeJpgFop, pipeline, null, force, type);
100+
PfopResult pfopRet = manager.Pfop(
101+
Bucket,
102+
key,
103+
fops,
104+
null,
105+
null,
106+
true,
107+
type,
108+
workflowId
109+
);
65110
if (pfopRet.Code != (int)HttpCode.OK)
66111
{
67-
Assert.Fail("pfop error: " + pfopRet.ToString());
112+
Assert.Fail("pfop error: " + pfopRet);
68113
}
69114

70115
PrefopResult prefopRet = manager.Prefop(pfopRet.PersistentId);
71116
if (prefopRet.Code != (int)HttpCode.OK)
72117
{
73-
Assert.Fail("prefop error: " + prefopRet.ToString());
118+
Assert.Fail("prefop error: " + prefopRet);
74119
}
75-
Assert.AreEqual(1, prefopRet.Result.Type);
120+
76121
Assert.IsNotNull(prefopRet.Result.CreationDate);
77122
Assert.IsNotEmpty(prefopRet.Result.CreationDate);
123+
124+
if (type == 1)
125+
{
126+
Assert.AreEqual(1, prefopRet.Result.Type);
127+
}
128+
129+
if (!string.IsNullOrEmpty(workflowId))
130+
{
131+
Assert.IsNotNull(prefopRet.Result.TaskFrom);
132+
Assert.IsNotEmpty(prefopRet.Result.TaskFrom);
133+
Assert.IsTrue(prefopRet.Result.TaskFrom.Contains(workflowId));
134+
}
78135
}
79136
}
80137
}

0 commit comments

Comments
 (0)