[FunctionName("HttpStartSingle")]
public static async Task<HttpResponseMessage> RunSingle(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}/{instanceId}")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
string functionName,
string instanceId,
ILogger log)
{
// Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
var existingInstance = await starter.GetStatusAsync(instanceId);
if (existingInstance == null
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
{
// An instance with the specified ID doesn't exist or an existing one stopped running, create one.
dynamic eventData = await req.Content.ReadAsAsync<object>();
await starter.StartNewAsync(functionName, instanceId, eventData);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
else
{
// An instance with the specified ID exists or an existing one still running, don't create one.
return new HttpResponseMessage(HttpStatusCode.Conflict)
{
Content = new StringContent($"An instance with ID '{instanceId}' already exists."),
};
}
}
注意
前面的 C# 代码适用于 Durable Functions 2.x。 对于 Durable Functions 1.x,必须使用 OrchestrationClient
属性而不是 DurableClient
属性,并且必须使用 DurableOrchestrationClient
参数类型而不是 IDurableOrchestrationClient
。 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。
function.json
{
"bindings": [
{
"authLevel": "function",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}/{instanceId}",
"methods": ["post"]
},
{
"name": "starter",
"type": "orchestrationClient",
"direction": "in"
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
]
}
index.js
const df = require("durable-functions");
module.exports = async function(context, req) {
const client = df.getClient(context);
const instanceId = req.params.instanceId;
const functionName = req.params.functionName;
// Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
const existingInstance = await client.getStatus(instanceId);
if (!existingInstance
|| existingInstance.runtimeStatus == "Completed"
|| existingInstance.runtimeStatus == "Failed"
|| existingInstance.runtimeStatus == "Terminated") {
// An instance with the specified ID doesn't exist or an existing one stopped running, create one.
const eventData = req.body;
await client.startNew(functionName, instanceId, eventData);
context.log(`Started orchestration with ID = '${instanceId}'.`);
return client.createCheckStatusResponse(req, instanceId);
} else {
// An instance with the specified ID exists or an existing one still running, don't create one.
return {
status: 409,
body: `An instance with ID '${instanceId}' already exists.`,
};
}
};
function.json
{
"bindings": [
{
"authLevel": "function",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}/{instanceId}",
"methods": ["post"]
},
{
"name": "starter",
"type": "orchestrationClient",
"direction": "in"
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
]
}
init.py
import logging
import azure.functions as func
import azure.durable_functions as df
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
client = df.DurableOrchestrationClient(starter)
instance_id = req.route_params['instanceId']
function_name = req.route_params['functionName']
existing_instance = await client.get_status(instance_id)
if existing_instance.runtime_status in [df.OrchestrationRuntimeStatus.Completed, df.OrchestrationRuntimeStatus.Failed, df.OrchestrationRuntimeStatus.Terminated, None]:
event_data = req.get_body()
instance_id = await client.start_new(function_name, instance_id, event_data)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
return client.create_check_status_response(req, instance_id)
else:
return {
'status': 409,
'body': f"An instance with ID '${existing_instance.instance_id}' already exists"
}
@FunctionName("HttpStartSingle")
public HttpResponseMessage runSingle(
@HttpTrigger(name = "req") HttpRequestMessage<?> req,
@DurableClientInput(name = "durableContext") DurableClientContext durableContext) {
String instanceID = "StaticID";
DurableTaskClient client = durableContext.getClient();
// Check to see if an instance with this ID is already running
OrchestrationMetadata metadata = client.getInstanceMetadata(instanceID, false);
if (metadata.isRunning()) {
return req.createResponseBuilder(HttpStatus.CONFLICT)
.body("An instance with ID '" + instanceID + "' already exists.")
.build();
}
// No such instance exists - create a new one. De-dupe is handled automatically
// in the storage layer if another function tries to also use this instance ID.
client.scheduleNewOrchestrationInstance("MyOrchestration", null, instanceID);
return durableContext.createCheckStatusResponse(req, instanceID);
}
默认情况下,实例 ID 是随机生成的 GUID。 但是,在前面的示例中,实例 ID 通过 URL 在路由数据中传递。 然后,代码提取业务流程实例元数据,用于检查具有指定 ID 的实例是否已运行。 如果没有此类实例正在运行,将使用该 ID 创建一个新实例。