إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
نمط التفاعل البشري يصف سير العمل الذي يتوقف وينتظر مدخلات الشخص قبل أن يستمر. هذا النمط مفيد لسير عمل الموافقة، والمصادقة متعددة العوامل، وأي سيناريو يستجيب فيه الشخص خلال فترة زمنية محددة.
على مستوى عام، يعمل النمط كما يلي:
- يقوم المنسق بالاتصال بنشاط لإبلاغ شخص (إرسال رمز SMS، أو إرسال بريد إلكتروني للمضيف، وهكذا).
- يبدأ المنسق مؤقتا مدوما وينتظر في الوقت نفسه حدثا خارجيا من الشخص.
- إذا استجاب الشخص قبل أن ينطلق المؤقت، يقوم المنسق بمعالجة الرد.
- إذا أطلق المؤقت أولا، يتولى المنسق المهلة (على سبيل المثال، برفض الطلب).
في هذه المقالة:
- نظرة عامة على سيناريو التفاعل البشري - لماذا هذا النمط مهم
- تعريف المنسق - تنفيذ سباق المؤقت مقابل الحدث
- تعريف الأنشطة - إرسال الإشعارات ومعالجة النتائج
- تشغيل عينة التفاعل البشري - اختبر سير العمل من البداية إلى النهاية
ملحوظة
تظهر محاور حزمة تطوير المهام المتطورة Durable Functions وDurable Task نفس النمط مع سيناريوهات مختلفة: Durable Functions تستخدم مثال التحقق من الهاتف SMS، بينما تستخدم مجموعات تطوير المهام المتطورة مثال سير عمل موافقة.
توضح هذه العينة كيفية بناء تنسيق Durable Functions يشمل التفاعل البشري. يطبق المثال نظام تحقق هاتفي قائم على الرسائل النصية النصية. هذا شائع في التحقق من رقم الهاتف وتدفقات التحقق من العوامل متعددة العوامل (MFA).
ملحوظة
تتوفر عينات كاملة من الكود للغات C# وJavaScript وPython. عينات PowerShell و Java غير متوفرة حاليا.
ملحوظة
الإصدار الرابع من نموذج البرمجة Node.js ل دالات Azure متوفر بشكل عام. تم تصميم نموذج v4 لتوفير تجربة أكثر مرونة وسهولة لمطوري JavaScript وTypeScript. لمزيد من المعلومات حول الفروقات بين v3 و v4، راجع دليل الهجرة.
في مقتطفات الكود التالية، تشير جافاسكريبت (PM4) إلى نموذج البرمجة v4، وهو التجربة الجديدة.
المتطلبات المسبقه
- إكمال مقالة التشغيل السريع
- قم باستنساخ أو تحميل مشروع العينات من GitHub
توضح هذه المقالة كيفية تنفيذ نمط التفاعل البشري باستخدام مجموعات تطوير المهام الدائمة. ينفذ المثال سير عمل موافقة حيث ينتظر التنسيق حتى يوافق أو يرفض الشخص على طلب قبل أن يستمر.
نظرة عامة على سيناريو التفاعل البشري
التحقق عبر الهاتف يساعد في التأكد من أن الأشخاص الذين يستخدمون تطبيقك ليسوا مرسلين مزعجين وأنهم يتحكمون في رقم الهاتف الذي يقدمونه. المصادقة متعددة العوامل هي طريقة شائعة لحماية الحسابات. بناء التحقق الخاص من هاتفك يتطلب تفاعلا مع شخص بحالة محددة. عادة ما يحصل المستخدم على رمز (على سبيل المثال، رقم مكون من أربعة أرقام) ويجب عليه الرد في وقت معقول.
دالات Azure القياسية هي بدون حالة (مثل العديد من نقاط النهاية السحابية الأخرى)، لذا يتطلب هذا النوع من التفاعل تخزين الحالة في قاعدة بيانات أو مخزن دائم آخر. كما أنك تقسم التفاعل بين عدة وظائف وتنسقها. على سبيل المثال، تقوم إحدى الوظائف بإنشاء رمز، وتخزينه، وإرساله إلى هاتف المستخدم. تستقبل دالة أخرى رد المستخدم وتربط الطلب الأصلي للتحقق من صحة الرمز. أضف مهلة توقف للمساعدة في حماية الأمن. هذا السير يصبح معقدا بسرعة.
يقلل Durable Functions من تعقيد هذا السيناريو. في هذه العينة، تدير دالة المنسق التفاعل الحالة دون وجود مخزن بيانات خارجي. نظرا لأن وظائف الأوركستراتور متينة، فإن هذه التدفقات التفاعلية موثوقة للغاية.
تعد سير العمل للموافقة شائعة في تطبيقات الأعمال حيث يجب مراجعة الطلب من قبل شخص قبل المتابعة. متطلبات سير العمل هي:
- انتظر إلى أجل غير مسمى رد فعل بشري، أو حتى انتهاء الوقت
- التعامل مع نتائج الموافقة والرفض معا
- الدعم يتوقف عند عدم تلقي أي رد
- تتبع الحالة حتى يتمكن الطالب من التحقق من التقدم
تبسط مجموعات تطوير المهام المتطورة هذا السيناريو ب:
- الأحداث الخارجية: يمكن للتنسيق التنسيقي التوقف والانتظار لحدث يثاره نظام أو مستخدم خارجي
- مؤقتات متينة: اضبط مهلة توقف تعمل إذا لم يتم استقبال أي رد
- الحالة المخصصة: تتبع وعرض حالة سير العمل الحالية للعملاء
تكوين تكامل Twilio
تتضمن هذه العينة استخدام خدمة Twilio من أجل إرسال رسائل SMS إلى هاتف جوال. دالات Azure يدعم بالفعل Twilio عبر Twilio binding، وتستخدم العينة هذه الميزة.
أول شيء بحاجة إليه هو حساب Twilio. يُصبح بإمكانك إنشاء حساب مجاني في https://www.twilio.com/try-twilio. بمجرد أن يكون لديك حساب، قم بإضافةإعدادات التطبيق الثلاثة التالية إلى تطبيق الوظائف.
| اسم إعداد التطبيق | وصف القيمة |
|---|---|
| TwilioAccountSid | معرّف الأمان فيما يتعلق بحساب Twilio الخاص بك |
| TwilioAuthToken | رمز المصادقة المُميز لحساب Twilio الخاص بك |
| TwilioPhoneNumber | رقم الهاتف المرتبط بحسابك على Twilio. يُستخدم هذا لإرسال رسائل SMS. |
تعريف الموزع
وظيفة المنسق E4_SmsPhoneVerification
نموذج العامل المعزول
using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
public static partial class PhoneVerification
{
[Function("E4_SmsPhoneVerification")]
public static async Task<bool> Run(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
string phoneNumber = context.GetInput<string>()
?? throw new ArgumentNullException(
nameof(phoneNumber),
"A phone number input is required.");
int challengeCode = await context.CallActivityAsync<int>(
"E4_SendSmsChallenge",
phoneNumber);
using var timeoutCts = new CancellationTokenSource();
// The user has 90 seconds to respond with the code they received.
DateTime expiration = context.CurrentUtcDateTime.AddSeconds(90);
Task timeoutTask = context.CreateTimer(expiration, timeoutCts.Token);
bool authorized = false;
for (int retryCount = 0; retryCount <= 3; retryCount++)
{
Task<int> challengeResponseTask =
context.WaitForExternalEvent<int>("SmsChallengeResponse");
Task winner = await Task.WhenAny(challengeResponseTask, timeoutTask);
if (winner == challengeResponseTask)
{
if (challengeResponseTask.Result == challengeCode)
{
authorized = true;
break;
}
}
else
{
break;
}
}
if (!timeoutTask.IsCompleted)
{
// All pending timers must complete or be canceled before the function exits.
timeoutCts.Cancel();
}
return authorized;
}
}
ملحوظة
هذا المنظم حتمي لأنه CurrentUtcDateTime يعيد نفس القيمة في نفس النقطة في كل إعادة تشغيل. يضمن هذا السلوك أن يكون winner ذلك نفسه لكل استدعاء متكرر ل Task.WhenAny.
النموذج أثناء العملية
[FunctionName("E4_SmsPhoneVerification")]
public static async Task<bool> Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
string phoneNumber = context.GetInput<string>();
if (string.IsNullOrEmpty(phoneNumber))
{
throw new ArgumentNullException(
nameof(phoneNumber),
"A phone number input is required.");
}
int challengeCode = await context.CallActivityAsync<int>(
"E4_SendSmsChallenge",
phoneNumber);
using (var timeoutCts = new CancellationTokenSource())
{
// The user has 90 seconds to respond with the code they received in the SMS message.
DateTime expiration = context.CurrentUtcDateTime.AddSeconds(90);
Task timeoutTask = context.CreateTimer(expiration, timeoutCts.Token);
bool authorized = false;
for (int retryCount = 0; retryCount <= 3; retryCount++)
{
Task<int> challengeResponseTask =
context.WaitForExternalEvent<int>("SmsChallengeResponse");
Task winner = await Task.WhenAny(challengeResponseTask, timeoutTask);
if (winner == challengeResponseTask)
{
// We got back a response! Compare it to the challenge code.
if (challengeResponseTask.Result == challengeCode)
{
authorized = true;
break;
}
}
else
{
// Timeout expired
break;
}
}
if (!timeoutTask.IsCompleted)
{
// All pending timers must be complete or canceled before the function exits.
timeoutCts.Cancel();
}
return authorized;
}
}
ملحوظة
قد لا يكون واضحا في البداية، لكن هذا الموزع لا ينتهك قيد التوزيع الحتمي. هي حتمية لأن الخاصية CurrentUtcDateTime تحسب وقت انتهاء صلاحية المؤقت، وتعيد نفس القيمة في كل إعادة تشغيل في هذه المرحلة من كود الأوركستراتور. يضمن هذا السلوك أن يكون winner ذلك نفسه لكل استدعاء متكرر ل Task.WhenAny.
بمجرد التشغيل، تقوم وظيفة التنسيق هذه بالخطوات التالية:
- يحصل على رقم هاتف لإرسال إشعار الرسائل النصية إليه.
- يتصل E4_SendSmsChallenge لإرسال رسالة SMS للمستخدم ويعيد رمز التحدي المتوقع المكون من أربعة أرقام.
- ينشئ مؤقتا متين يعمل بعد 90 ثانية من الوقت الحالي.
- بالتوازي مع المؤقت، ينتظر حدث SmsChallengeResponse من المستخدم.
يتلقى المستخدم رسالة SMS مع رمز من أربعة أرقام. لديهم 90 ثانية لإرسال نفس الكود إلى مثيل المنسق لإكمال التحقق. إذا قدموا كودا خاطئا، يحصلون على ثلاث محاولات إضافية خلال نفس نافذة ال 90 ثانية.
التحذير
ألغ المؤقتات التي لم تعد بحاجة إليها. في المثال السابق، يقوم التوزيع الموسيقي بإلغاء المؤقت عند قبول استجابة التحدي.
يقدم المنسق طلب موافقة، ثم ينتظر إما رد بشري أو وقت مستقطع.
using Microsoft.DurableTask;
using System;
using System.Threading;
using System.Threading.Tasks;
[DurableTask(nameof(ApprovalOrchestration))]
public class ApprovalOrchestration : TaskOrchestrator<ApprovalRequestData, ApprovalResult>
{
public override async Task<ApprovalResult> RunAsync(
TaskOrchestrationContext context, ApprovalRequestData input)
{
string requestId = input.RequestId;
double timeoutHours = input.TimeoutHours;
// Step 1: Submit the approval request (notify approver)
SubmissionResult submissionResult = await context.CallActivityAsync<SubmissionResult>(
nameof(SubmitApprovalRequestActivity), input);
// Make the status available via custom status
context.SetCustomStatus(submissionResult);
// Step 2: Create a durable timer for the timeout
DateTime timeoutDeadline = context.CurrentUtcDateTime.AddHours(timeoutHours);
using var timeoutCts = new CancellationTokenSource();
Task timeoutTask = context.CreateTimer(timeoutDeadline, timeoutCts.Token);
// Step 3: Wait for an external event (approval/rejection)
Task<ApprovalResponseData> approvalTask = context.WaitForExternalEvent<ApprovalResponseData>(
"approval_response");
// Step 4: Wait for either the timeout or the approval response
Task completedTask = await Task.WhenAny(approvalTask, timeoutTask);
// Step 5: Process based on which task completed
ApprovalResult result;
if (completedTask == approvalTask)
{
// Human responded in time - cancel the timeout timer
timeoutCts.Cancel();
ApprovalResponseData approvalData = approvalTask.Result;
// Process the approval
result = await context.CallActivityAsync<ApprovalResult>(
nameof(ProcessApprovalActivity),
new ProcessApprovalInput
{
RequestId = requestId,
IsApproved = approvalData.IsApproved,
Approver = approvalData.Approver
});
}
else
{
// Timeout occurred
result = new ApprovalResult
{
RequestId = requestId,
Status = "Timeout",
ProcessedAt = context.CurrentUtcDateTime.ToString("o")
};
}
return result;
}
}
يقوم هذا الموزع بأداء الأفعال التالية:
- يقدم طلب الموافقة عن طريق استدعاء نشاط يخطر المعترض.
- يضبط الحالة المخصصة حتى يتمكن العملاء من تتبع التقدم.
- ينشئ مؤقتا متيما لموعد انتهاء المهلة.
- ينتظر حدثا خارجيا (
approval_response) يطرحه المعترف. - يستخدم
WhenAny،when_any، أوanyOfالانتظار لما يكتمل أولا: الموافقة أو المهلة. - يعالج النتيجة بناء على المهمة التي تكملها.
التحذير
ألغ المؤقتات التي لم تعد بحاجة إليها. في مثال C#، يقوم التوزيع الموسيقي بإلغاء مؤقت المهلة عند حصوله على الموافقة.
تعريف الأنشطة
وظيفة نشاط E4_SendSmsChallenge
ترسل وظيفة E4_SendSmsChallenge رسالة SMS تتضمن رمزا مكون من أربعة أرقام إلى المستخدم.
نموذج العامل المعزول
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;
public static partial class PhoneVerification
{
[Function("E4_SendSmsChallenge")]
public static async Task<int> SendSmsChallenge(
[ActivityTrigger] string phoneNumber,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("E4_SendSmsChallenge");
int challengeCode = Random.Shared.Next(10000);
logger.LogInformation(
"Sending verification code {ChallengeCode:0000} to {PhoneNumber}.",
challengeCode,
phoneNumber);
string accountSid = Environment.GetEnvironmentVariable("TwilioAccountSid")
?? throw new InvalidOperationException("TwilioAccountSid is not configured.");
string authToken = Environment.GetEnvironmentVariable("TwilioAuthToken")
?? throw new InvalidOperationException("TwilioAuthToken is not configured.");
string fromNumber = Environment.GetEnvironmentVariable("TwilioPhoneNumber")
?? throw new InvalidOperationException("TwilioPhoneNumber is not configured.");
TwilioClient.Init(accountSid, authToken);
await MessageResource.CreateAsync(
to: new PhoneNumber(phoneNumber),
from: new PhoneNumber(fromNumber),
body: $"Your verification code is {challengeCode:0000}");
return challengeCode;
}
}
ملحوظة
لتشغيل عينة العامل المعزولة، قم بتثبيت Twilio حزمة NuGet. قم بضبط TwilioAccountSidإعدادات ، TwilioAuthToken، والتطبيق TwilioPhoneNumber .
النموذج أثناء العملية
[FunctionName("E4_SendSmsChallenge")]
public static int SendSmsChallenge(
[ActivityTrigger] string phoneNumber,
ILogger log,
[TwilioSms(AccountSidSetting = "TwilioAccountSid", AuthTokenSetting = "TwilioAuthToken", From = "%TwilioPhoneNumber%")]
out CreateMessageOptions message)
{
// Get a random number generator with a random seed (not time-based)
var rand = new Random(Guid.NewGuid().GetHashCode());
int challengeCode = rand.Next(10000);
log.LogInformation($"Sending verification code {challengeCode} to {phoneNumber}.");
message = new CreateMessageOptions(new PhoneNumber(phoneNumber));
message.Body = $"Your verification code is {challengeCode:0000}";
return challengeCode;
}
ملحوظة
لتشغيل العينة، قم بتثبيت حزمة Microsoft.Azure.WebJobs.Extensions.Twilio NuGet. لا تثبت حزمة Twilio NuGet الرئيسية لأنها قد تسبب تعارضات في الإصدارات وأخطاء في البناء.
تقوم الأنشطة بتقديم طلب الموافقة ومعالجة الرد.
نشاط طلب الموافقة على تقديم
using Microsoft.DurableTask;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
[DurableTask(nameof(SubmitApprovalRequestActivity))]
public class SubmitApprovalRequestActivity : TaskActivity<ApprovalRequestData, SubmissionResult>
{
private readonly ILogger<SubmitApprovalRequestActivity> _logger;
public SubmitApprovalRequestActivity(ILogger<SubmitApprovalRequestActivity> logger)
{
_logger = logger;
}
public override Task<SubmissionResult> RunAsync(
TaskActivityContext context, ApprovalRequestData input)
{
_logger.LogInformation(
"Submitting approval request {RequestId} from {Requester} for {Item}",
input.RequestId, input.Requester, input.Item);
// In a real system, this would send an email, notification, or update a database
var result = new SubmissionResult
{
RequestId = input.RequestId,
Status = "Pending",
SubmittedAt = DateTime.UtcNow.ToString("o"),
ApprovalUrl = $"http://localhost:8000/api/approvals/{input.RequestId}"
};
return Task.FromResult(result);
}
}
نشاط الموافقة على العمليات
using Microsoft.DurableTask;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
[DurableTask(nameof(ProcessApprovalActivity))]
public class ProcessApprovalActivity : TaskActivity<ProcessApprovalInput, ApprovalResult>
{
private readonly ILogger<ProcessApprovalActivity> _logger;
public ProcessApprovalActivity(ILogger<ProcessApprovalActivity> logger)
{
_logger = logger;
}
public override Task<ApprovalResult> RunAsync(
TaskActivityContext context, ProcessApprovalInput input)
{
string status = input.IsApproved ? "Approved" : "Rejected";
_logger.LogInformation(
"Processing {Status} request {RequestId} by {Approver}",
status, input.RequestId, input.Approver);
// In a real system, this would update a database, trigger workflows, etc.
var result = new ApprovalResult
{
RequestId = input.RequestId,
Status = status,
ProcessedAt = DateTime.UtcNow.ToString("o"),
Approver = input.Approver
};
return Task.FromResult(result);
}
}
// Data classes
public class ApprovalRequestData
{
public string RequestId { get; set; } = string.Empty;
public string Requester { get; set; } = string.Empty;
public string Item { get; set; } = string.Empty;
public double TimeoutHours { get; set; } = 24.0;
}
public class ApprovalResponseData
{
public bool IsApproved { get; set; }
public string Approver { get; set; } = string.Empty;
}
public class SubmissionResult
{
public string RequestId { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string SubmittedAt { get; set; } = string.Empty;
public string ApprovalUrl { get; set; } = string.Empty;
}
public class ProcessApprovalInput
{
public string RequestId { get; set; } = string.Empty;
public bool IsApproved { get; set; }
public string Approver { get; set; } = string.Empty;
}
public class ApprovalResult
{
public string RequestId { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string ProcessedAt { get; set; } = string.Empty;
public string? Approver { get; set; }
}
تشغيل عينة التفاعل البشري
استخدم الوظائف التي يتم تفعيلها بواسطة HTTP في العينة لبدء التنسيق عن طريق إرسال طلب HTTP POST التالي:
POST http://{host}/orchestrators/E4_SmsPhoneVerification
Content-Length: 14
Content-Type: application/json
"+1425XXXXXXX"
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
{"id":"741c65651d4c40cea29acdd5bb47baf1",
"sendEventPostUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}",
"statusQueryGetUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1?taskHub=...&code={systemKey}",
"terminatePostUri":"http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/terminate?reason={text}&taskHub=...&code={systemKey}"}
تستقبل وظيفة المنسق رقم الهاتف وترسل فورا رسالة نصية إلى ذلك الرقم مع رمز تحقق عشوائي مكون من 4 أرقام—على سبيل المثال، 2168. ثم تنتظر الوظيفة 90 ثانية لاستجابة.
للرد بالكود، استخدم RaiseEventAsync (.NET) أو raiseEvent (JavaScript و TypeScript) في دالة أخرى، أو استدعي نقطة نهاية HTTP POST في الرد 202 sendEventPostUri HTTP POST. استبدل {eventName} ب SmsChallengeResponse:
POST http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1/raiseEvent/SmsChallengeResponse?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
Content-Length: 4
Content-Type: application/json
2168
إذا أرسلت الحدث قبل انتهاء المؤقت، يكتمل التوزيع الموسيقي، ويتم تعيين output الحقل على true، مما يشير إلى نجاح التأكيد.
GET http://{host}/runtime/webhooks/durabletask/instances/741c65651d4c40cea29acdd5bb47baf1?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
HTTP/1.1 200 OK
Content-Length: 144
Content-Type: application/json; charset=utf-8
{"runtimeStatus":"Completed","input":"+1425XXXXXXX","output":true,"createdTime":"2026-04-23T19:10:49Z","lastUpdatedTime":"2026-04-23T19:12:23Z"}
إذا انتهى المؤقت أو أدخلت رمزا خاطئا أربع مرات، استعلام الحالة لرؤية output التعيين على false، مما يشير إلى فشل التحقق من الهاتف.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 145
{"runtimeStatus":"Completed","input":"+1425XXXXXXX","output":false,"createdTime":"2026-04-23T19:20:49Z","lastUpdatedTime":"2026-04-23T19:22:23Z"}
لتشغيل العينة:
ابدأ محاكي جدولة المهام الدائمة للتطوير المحلي. يجب تثبيت Docker.
docker run -d -p 8080:8080 -p 8082:8082 --name dts-emulator mcr.microsoft.com/dts/dts-emulator:latestابدأ العامل بتسجيل المنظم والأنشطة.
شغل العميل لجدولة سير عمل الموافقة وإرسال الأحداث.
using System;
using System.Threading.Tasks;
var client = DurableTaskClientBuilder.UseDurableTaskScheduler(connectionString).Build();
// Schedule the approval workflow
var input = new ApprovalRequestData
{
RequestId = "request-" + Guid.NewGuid().ToString(),
Requester = "john.doe@example.com",
Item = "Vacation Request - 5 days",
TimeoutHours = 24
};
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(ApprovalOrchestration), input);
Console.WriteLine($"Started approval workflow: {instanceId}");
// Simulate human approving the request
Console.WriteLine("Simulating approval...");
await Task.Delay(2000);
// Raise the approval event
var approvalResponse = new ApprovalResponseData
{
IsApproved = true,
Approver = "manager@example.com"
};
await client.RaiseEventAsync(instanceId, "approval_response", approvalResponse);
// Wait for completion
var result = await client.WaitForInstanceCompletionAsync(instanceId, getInputsAndOutputs: true);
Console.WriteLine($"Result: {result.ReadOutputAs<ApprovalResult>().Status}");
الخطوات التالية
تظهر هذه العينة قدرات Durable Functions متقدمة، بما في ذلك واجهات برمجة التطبيقات WaitForExternalEvent و CreateTimer. يوضح كيفية دمج Task.WhenAny (C#)، context.df.Task.any (جافا سكريبت وTypeScript)، أو context.task_any (Python) لتنفيذ نمط مهلة موثوقة لسير العمل الذي ينتظر استجابة الناس.
توضح هذه العينة كيفية استخدام مجموعات تطوير المهام المتطورة لتنفيذ سير عمل تنتظر استجابة الناس، مع مهلات زمنية قابلة للتكوين. المفاهيم الأساسية:
-
الأحداث الخارجية: استخدام
WaitForExternalEventانتظار المدخلات -
مؤقتات متينة: استخدامها
CreateTimerلتنفيذ المهمات المفتوحة -
مهام السباق: استخدام
WhenAny،when_any، أوanyOfللتعامل مع المهمة التي تكتمل أولا