إدارة حالات التوزيع الموسيقي

استخدم واجهات برمجة التطبيقات المدمجة لإدارة العينات لبدء واستعلام وإنهاء وتعليق واستئناف وإزالة حالات التنسيق في سير العمل الدائم الخاص بك. في Durable Functions، يكشف ربط عميل orchestration هذه واجهات برمجة التطبيقات. في مجموعات تطوير المهام الدائمة، تتوفر نفس العمليات من خلال الفئة DurableTaskClient . توضح هذه المقالة كيفية تنفيذ كل عملية إدارة مثيل باستخدام أمثلة كود لكلا المنصتين.

نصيحة

جدولة المهام المتطورة Azure هي الواجهة الخلفية الموصى بها لكل من Durable Functions وحزمة تطوير المهام الدائمة، وتوفر تجربة مدارة بالكامل بدون خوادم لتشغيل سير العمل المتطور على نطاق واسع.

بدء مثيلات

طريقة start-new (أو schedule-new) على عميل التوزيع تبدأ نسخة تنسيق جديدة. داخليا، تكتب هذه الطريقة رسالة إلى الخلفية المعدة (مثل جدولة المهام الدائمة) ثم تعيد. تقوم هذه الرسالة بتفعيل بدء التوزيع الموسيقي بالاسم المحدد.

إليك المعايير لبدء نسخة جديدة من التوزيع الأوركسترالي:

مهم

سينتهي الدعم للنموذج قيد التنفيذ في 10 نوفمبر 2026. نوصي بشدة بترحيل تطبيقاتك إلى نموذج العامل المعزول للحصول على الدعم الكامل.

المعلمة الوصف
الاسم اسم الموزع لوظيفة الجدول الزمني.
الادخال أي بيانات قابلة للتسلسل عبر JSON يجب أن تمرر كمدخل إلى وظيفة المنسق.
معرف المثيل (اختياري) المعرف الفريد للمثال. إذا لم تحدد هذه المعلمة، فإن الأسلوب يستخدم معرفا عشوائيا.

نصيحة

استخدم معرفا عشوائيا لمعرف المثيل كلما أمكن ذلك. تساعد معرفات العينات العشوائية في ضمان توزيع متساو للحمل عند توسيع وظائف الأوركستراتور عبر عدة أجهزة افتراضية. الوقت المناسب لاستخدام معرفات العينات غير العشوائية هو عندما يأتي المعرف من مصدر خارجي أو عندما تقوم بتنفيذ نمط التنسيق الأحادي .

المعلمة الوصف
الاسم اسم الفرقة الموسيقية حسب الجدول.
الادخال أي بيانات قابلة للتسلسل عبر JSON يجب أن تمرر كمدخلات إلى التنسيق.
معرف المثيل (اختياري) المعرف الفريد للمثال. إذا لم تحدد هذه المعلمة، فإن الأسلوب يستخدم معرفا عشوائيا.

نصيحة

استخدم معرفا عشوائيا لمعرف المثيل كلما أمكن ذلك. تساعد معرفات العينات العشوائية في ضمان توزيع متساو للحمل عند توسيع التوزيع عبر عدة أجهزة افتراضية. الوقت المناسب لاستخدام معرفات العينات غير العشوائية هو عندما يأتي المعرف من مصدر خارجي أو عندما تقوم بتنفيذ نمط التنسيق الأحادي .

تبدأ دالة المثال التالية نسخة توزيع جديدة:

نموذج العامل المعزول
[Function("HelloWorldQueueTrigger")]
public static async Task Run(
    [QueueTrigger("start-queue")] string input,
    [DurableClient] DurableTaskClient client,
    FunctionContext functionContext)
{
    string instanceId = await client.ScheduleNewOrchestrationInstanceAsync("HelloWorld", input);
    functionContext.GetLogger("HelloWorldQueueTrigger")
        .LogInformation("Started orchestration with ID = '{InstanceId}'.", instanceId);
}

النموذج أثناء العملية
[FunctionName("HelloWorldQueueTrigger")]
public static async Task Run(
    [QueueTrigger("start-queue")] string input,
    [DurableClient] IDurableOrchestrationClient starter,
    ILogger log)
{
    string instanceId = await starter.StartNewAsync("HelloWorld", input);
    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
}

مهم

حاليا، حزمة تطوير المهام الدائمة PowerShell غير متوفرة.

يوضح الكود التالي كيفية بدء نسخة تنسيقية جديدة باستخدام مجموعات SDK للمهام الدائمة:

using Microsoft.DurableTask.Client;

// Schedule a new orchestration instance
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync("HelloWorld", input);
Console.WriteLine($"Started orchestration with ID = '{instanceId}'.");

// Optionally, wait for the orchestration to start
OrchestrationMetadata metadata = await client.WaitForInstanceStartAsync(instanceId, timeout: TimeSpan.FromSeconds(30));

مثيلات الاستعلام

بعد بدء نسخ تنسيق جديدة، من المرجح أنك بحاجة للاستعلام عن حالة وقت التشغيل الخاصة بها لمعرفة ما إذا كانت تعمل أو مكتملة أو فاشلة.

طريقة الحصول على الحالة على عميل التنسيق تعيد حالة مثيل التنسيق.

يأخذ instanceId (مطلوب) و showHistory (اختياري) showHistoryOutput و(اختياري) و showInput (اختياري) كمعلمات.

  • showHistory: إذا تم تعيينها إلى true، تحتوي الاستجابة على محفوظات التنفيذ.
  • showHistoryOutput: إذا تم تعيينه إلى true، يحتوي سجل التنفيذ على مخرجات النشاط.
  • showInput: إذا تم تعيينه على false، فإن الاستجابة لا تحتوي على مدخل الدالة. القيمة الافتراضية هي true.

يقوم الأسلوب بإرجاع كائن بالخصائص التالية:

الملكية الوصف
الاسم اسم وظيفة الموزع.
معرف المثيل معرف النسخة في التوزيع (يجب أن يكون هو نفسه instanceId المدخل).
وقت الإنشاء الوقت الذي تبدأ فيه وظيفة الموزع في العمل.
آخر تحديث لوقت الوقت الذي يستمر فيه التوزيع الموسيقي في نقاط التفتيش.
الادخال إدخال الدالة كقيمة JSON. هذا الحقل غير مأهول إذا showInput كان .false
حالة التخصيص حالة توزيع مخصص بتنسيق JSON.
الإنتاج مخرج الدالة كقيمة JSON (إذا اكتملت الدالة). إذا فشلت وظيفة المنسق، تشمل هذه الخاصية تفاصيل الفشل. إذا تم تعليق أو إنهاء وظيفة المنسق، فإن هذه الخاصية تشمل سبب التعليق أو الإنهاء (إن وجد).
مدة التشغيلالحالة: قيد الانتظار تم جدولة النسخة لكنها لم تبدأ العمل بعد.
مدة التشغيل: قيد التشغيل الجهاز يعمل.
مدة التشغيلالحالة: اكتمل تم إكمال النسخة بشكل طبيعي.
مدة العرض: مستمر كجديد أعادت النسخة تشغيل نفسها بتاريخ جديد. هذه الحالة هي حالة عابرة.
حالة وقت التشغيل: فشل فشل النموذج مع خطأ.
مدة التشغيلالحالة: انتهى توقفت الحالة فجأة.
مدة العرض: تم تعليق يتم تعليق النسخة ويمكن استئنافها لاحقا.
التاريخ تاريخ تنفيذ التوزيع الأوركسترالي. يتم ملء هذا الحقل فقط إذا showHistory تم تعيينه إلى true.
المعلمة الوصف
showHistory إذا تم تعيينه على true، فإن الاستجابة تحتوي على سجل التنفيذ.
showHistoryOutput إذا تم تعيينه على true، فإن سجل التنفيذ يحتوي على مخرجات النشاط.
showInput إذا تم ضبطه على false، فإن الاستجابة لا تحتوي على مدخلات التوزيع الأوركسترالي. القيمة الافتراضية هي true.

يقوم الأسلوب بإرجاع كائن بالخصائص التالية:

الملكية الوصف
الاسم اسم الفرقة الموسيقية.
معرف المثيل معرف النسخة في التوزيع (يجب أن يكون هو نفسه instanceId المدخل).
وقت الإنشاء الوقت الذي يبدأ فيه التوزيع الموسيقي.
آخر تحديث لوقت الوقت الذي يستمر فيه التوزيع الموسيقي في نقاط التفتيش.
الادخال إدخال التوزيع كقيمة JSON. هذا الحقل غير مأهول إذا showInput كان .false
حالة التخصيص حالة توزيع مخصص بتنسيق JSON.
الإنتاج خرج التوزيع كقيمة JSON (إذا اكتمل التوزيع الموسيقي). إذا فشل التنسيق، تشمل هذه الخاصية تفاصيل الفشل. إذا تم تعليق أو إنهاء التنظيم، فإن هذه الخاصية تشمل سبب الإيقاف أو الإنهاء (إن وجد).
مدة التشغيلالحالة: قيد الانتظار تم جدولة النسخة لكنها لم تبدأ العمل بعد.
مدة التشغيل: قيد التشغيل الجهاز يعمل.
مدة التشغيلالحالة: اكتمل تم إكمال النسخة بشكل طبيعي.
مدة العرض: مستمر كجديد أعادت النسخة تشغيل نفسها بتاريخ جديد. هذه الحالة هي حالة عابرة.
حالة وقت التشغيل: فشل فشل النموذج مع خطأ.
مدة التشغيلالحالة: انتهى توقفت الحالة فجأة.
مدة العرض: تم تعليق يتم تعليق النسخة ويمكن استئنافها في وقت لاحق.
التاريخ تاريخ تنفيذ التوزيع الأوركسترالي. يتم ملء هذا الحقل فقط إذا showHistory تم تعيينه إلى true.

ملحوظة

لا يتم وضع علامة على الموزع حتى Completed تنتهي جميع مهامه المجدولة ويعود الموزع. بعبارة أخرى، ليس كافيا أن يصل الموزع إلى بيانه return ليتم تمييزه ك Completed. وهذا مهم بشكل خاص في الحالات التي WhenAny يستخدم؛ غالبا return ما يكون هؤلاء المنظمون قبل تنفيذ جميع المهام المجدولة.

تعود هذه الطريقة ب null (.NET و Java)، undefined (جافا سكريبت)، أو None (Python) إذا لم يكن المثيل موجودا.

نموذج العامل المعزول
[Function("GetStatus")]
public static async Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("check-status-queue")] string instanceId)
{
    OrchestrationMetadata? metadata = await client.GetInstanceAsync(
        instanceId,
        getInputsAndOutputs: true);
    // Do something based on the current status.
}

النموذج أثناء العملية
[FunctionName("GetStatus")]
public static async Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("check-status-queue")] string instanceId)
{
    DurableOrchestrationStatus status = await client.GetStatusAsync(instanceId);
    // do something based on the current status.
}

using Microsoft.DurableTask.Client;

// Get the status of an orchestration instance
OrchestrationMetadata? metadata = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: true);
if (metadata != null)
{
    OrchestrationRuntimeStatus status = metadata.RuntimeStatus;
    // do something based on the current status
}

استعلام جميع حالات التوزيع الموسيقي

يمكنك استخدام واجهات برمجة التطبيقات بلغتك SDK للاستعلام عن حالات جميع مثيلات التنسيق في مركز المهام. تقوم واجهة برمجة التطبيقات هذه "list-instances" أو "get-status" بإرجاع قائمة الكائنات التي تمثل مثيلات التنسيق المطابقة لمعلمات الاستعلام.

نموذج العامل المعزول
[Function("GetAllStatus")]
public static async Task Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData request,
    [DurableClient] DurableTaskClient client,
    FunctionContext functionContext)
{
    ILogger logger = functionContext.GetLogger("GetAllStatus");
    AsyncPageable<OrchestrationMetadata> instances = client.GetAllInstancesAsync(
        new OrchestrationQuery());

    await foreach (OrchestrationMetadata instance in instances)
    {
        logger.LogInformation("{Instance}", instance);
    }
}

النموذج أثناء العملية
[FunctionName("GetAllStatus")]
public static async Task Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient client,
    ILogger log)
{
    var noFilter = new OrchestrationStatusQueryCondition();
    OrchestrationStatusQueryResult result = await client.ListInstancesAsync(
        noFilter,
        CancellationToken.None);
    foreach (DurableOrchestrationStatus instance in result.DurableOrchestrationState)
    {
        log.LogInformation(JsonConvert.SerializeObject(instance));
    }

    // Note: ListInstancesAsync only returns the first page of results.
    // To request additional pages provide the result.ContinuationToken
    // to the OrchestrationStatusQueryCondition's ContinuationToken property.
}

using Microsoft.DurableTask.Client;

// Query all orchestration instances
AsyncPageable<OrchestrationMetadata> instances = client.GetAllInstancesAsync(new OrchestrationQuery());

await foreach (OrchestrationMetadata instance in instances)
{
    Console.WriteLine(instance.InstanceId);
}

استعلام مثيلات التنسيق باستخدام الفلاتر

ماذا لو لم تكن بحاجة لكل المعلومات التي توفرها استعلام الحالة القياسية؟ على سبيل المثال، ماذا لو كنت تبحث فقط عن وقت إنشاء الأوركسترا أو حالة مدة تشغيل الأوركسترا؟ ضيق نطاق استعلامك بتطبيق فلاتر.

نموذج العامل المعزول
[Function("QueryStatus")]
public static async Task Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData request,
    [DurableClient] DurableTaskClient client,
    FunctionContext functionContext)
{
    ILogger logger = functionContext.GetLogger("QueryStatus");
    var query = new OrchestrationQuery
    {
        Statuses = new[]
        {
            OrchestrationRuntimeStatus.Pending,
            OrchestrationRuntimeStatus.Running,
        },
        CreatedFrom = DateTime.UtcNow.Subtract(TimeSpan.FromDays(7)),
        CreatedTo = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)),
        PageSize = 100,
    };

    await foreach (OrchestrationMetadata instance in client.GetAllInstancesAsync(query))
    {
        logger.LogInformation("{Instance}", instance);
    }
}

النموذج أثناء العملية
[FunctionName("QueryStatus")]
public static async Task Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient client,
    ILogger log)
{
    // Get the first 100 running or pending instances that were created between 7 and 1 days ago
    var queryFilter = new OrchestrationStatusQueryCondition
    {
        RuntimeStatus = new[]
        {
            OrchestrationRuntimeStatus.Pending,
            OrchestrationRuntimeStatus.Running,
        },
        CreatedTimeFrom = DateTime.UtcNow.Subtract(TimeSpan.FromDays(7)),
        CreatedTimeTo = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)),
        PageSize = 100,
    };

    OrchestrationStatusQueryResult result = await client.ListInstancesAsync(
        queryFilter,
        CancellationToken.None);
    foreach (DurableOrchestrationStatus instance in result.DurableOrchestrationState)
    {
        log.LogInformation(JsonConvert.SerializeObject(instance));
    }
}

using Microsoft.DurableTask.Client;

// Get running or pending instances created in the last 7 days
var query = new OrchestrationQuery
{
    Statuses = new[] { OrchestrationRuntimeStatus.Running, OrchestrationRuntimeStatus.Pending },
    CreatedFrom = DateTime.UtcNow.AddDays(-7),
    CreatedTo = DateTime.UtcNow.AddDays(-1),
    PageSize = 100
};

AsyncPageable<OrchestrationMetadata> instances = client.GetAllInstancesAsync(query);

await foreach (OrchestrationMetadata instance in instances)
{
    Console.WriteLine($"{instance.InstanceId}: {instance.RuntimeStatus}");
}

إنهاء حالات التوزيع الموسيقي

إذا كان لديك حالة توزيع موسيقي تستغرق وقتا طويلا للتشغيل، أو تحتاج لإيقافها قبل اكتمالها لأي سبب، يمكنك إنهاؤها.

المعاملتان لواجهة برمجة التطبيقات النهائية هما معرف المثيل وسلسلة السبب ، اللذان يكتبان إلى السجلات وإلى حالة المثيل.

نموذج العامل المعزول
[Function("TerminateInstance")]
public static Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("terminate-queue")] string instanceId)
{
    string reason = "Found a bug";
    return client.TerminateInstanceAsync(instanceId, reason);
}

النموذج أثناء العملية
[FunctionName("TerminateInstance")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("terminate-queue")] string instanceId)
{
    string reason = "Found a bug";
    return client.TerminateAsync(instanceId, reason);
}

using Microsoft.DurableTask.Client;

string reason = "Found a bug";
await client.TerminateInstanceAsync(instanceId, reason);

النسخة المنتهية تنتقل في النهاية إلى Terminated الحالة. لكن هذا الانتقال لا يحدث فورا. بدلا من ذلك، يتم وضع عملية الإنهاء في قائمة الانتظار في مركز المهام مع عمليات أخرى لهذا النموذج. يمكنك استخدام واجهات برمجة تطبيقات استعلام المثيل لمعرفة متى وصل مثيل منتهى Terminated بالفعل إلى الحالة.

ملحوظة

لا يتم نشر إنهاء المثيل حاليا. وظائف النشاط والتنسيقات الفرعية تعمل حتى الاكتمال، بغض النظر عما إذا كنت تنهي نسخة التوزيع التي استدعتها.

تعليق واستئناف حالات التوزيع الموسيقي

تعليق التوزيع يسمح لك بإيقاف توزيع موسيقي مستمر. على عكس إنهاء التوزيع الأوركسترالي، يمكنك استئناف التوزيع الموسيقي المعلق لاحقا.

المعلمتان لواجهة برمجة تطبيقات الإيقاف المؤقت هي معرف مثيل وسلسلة سبب، والتي تتم كتابتها إلى السجلات وإلى حالة المثيل.

نموذج العامل المعزول
[Function("SuspendResumeInstance")]
public static async Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("suspend-resume-queue")] string instanceId)
{
    // To suspend an orchestration
    string suspendReason = "Need to pause workflow";
    await client.SuspendInstanceAsync(instanceId, suspendReason);

    // To resume an orchestration
    string resumeReason = "Continue workflow";
    await client.ResumeInstanceAsync(instanceId, resumeReason);
}

النموذج أثناء العملية
[FunctionName("SuspendResumeInstance")]
public static async Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("suspend-resume-queue")] string instanceId)
{
    // To suspend an orchestration
    string suspendReason = "Need to pause workflow";
    await client.SuspendAsync(instanceId, suspendReason);

    // To resume an orchestration
    string resumeReason = "Continue workflow";
    await client.ResumeAsync(instanceId, resumeReason);
}

using Microsoft.DurableTask.Client;

// To suspend an orchestration
string suspendReason = "Need to pause workflow";
await client.SuspendInstanceAsync(instanceId, suspendReason);

// To resume an orchestration
string resumeReason = "Continue workflow";
await client.ResumeInstanceAsync(instanceId, resumeReason);

تنتقل الحالة المعلقة في النهاية إلى Suspended الولاية. ومع ذلك، هذا الانتقال لا يحدث فورا. بدلا من ذلك، يتم وضع عملية التعليق في قائمة الانتظار في مركز المهام مع العمليات الأخرى في تلك الحالة. استخدم واجهات برمجة تطبيقات استعلام المثيل لمعرفة متى وصل المثيل الجاري فعليا إلى Suspended الحالة.

عند استئناف الموزع المعلق، يتغير حالته مرة أخرى إلى Running.

إرسال الأحداث إلى المثيلات

في بعض السيناريوهات، تحتاج وظائف المنسق إلى الانتظار والاستماع للأحداث الخارجية. من الأمثلة التي يكون فيها هذا النهج مفيدا سيناريوهات المراقبةوالتفاعل البشري .

في بعض السيناريوهات، تحتاج التوزيعات إلى الانتظار والاستماع للأحداث الخارجية. من الأمثلة التي يكون فيها هذا النهج مفيدا سيناريوهات المراقبةوالتفاعل البشري .

يمكنك إرسال إشعارات الأحداث إلى الإصدارات الجارية باستخدام واجهة برمجة تطبيقات Raise Event الخاصة بعميل التنسيق. يمكن للتنسيقات الاستماع إلى هذه الأحداث والاستجابة لها باستخدام انتظار واجهة برمجة تطبيقات منسق الأحداث الخارجية .

المعايير لحدث الرفع هي:

  • معرف المثيل: المعرف الفريد للمثيل.
  • اسم الحدث: اسم الحدث المراد إرساله.
  • بيانات الحدث: حمولة JSON قابلة للتسلسل لإرسالها إلى المثيل.
نموذج العامل المعزول
[Function("RaiseEvent")]
public static Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("event-queue")] string instanceId)
{
    int[] eventData = new int[] { 1, 2, 3 };
    return client.RaiseEventAsync(instanceId, "MyEvent", eventData);
}

النموذج أثناء العملية
[FunctionName("RaiseEvent")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("event-queue")] string instanceId)
{
    int[] eventData = new int[] { 1, 2, 3 };
    return client.RaiseEventAsync(instanceId, "MyEvent", eventData);
}

using Microsoft.DurableTask.Client;

int[] eventData = new int[] { 1, 2, 3 };
await client.RaiseEventAsync(instanceId, "MyEvent", eventData);

ملحوظة

إذا لم يكن هناك نسخة تنسيق بمعرف النسخة المحدد، يتم تجاهل رسالة الحدث. إذا كان هناك مثيل لكنه لم ينتظر الحدث بعد، يتم تخزين الحدث في حالة النسخة حتى يكون جاهزا للاستلام والمعالجة.

انتظر حتى اكتمال التنسيق

في التوزيعات الموسيقية طويلة الأمد، قد ترغب في الانتظار والحصول على نتائج التوزيع الأوركسترالي. في هذه الحالات، من المفيد أيضا تحديد فترة مهلة على التوزيع الأوركسترالي. إذا تم تجاوز المهلة، يتم إعادة حالة التوزيع بدلا من النتائج.

استخدم واجهة برمجة التطبيقات "انتظر الاكتمال أو إنشاء استجابة حالة المراجعة" للحصول على المخرج الفعلي من مثيل التنسيق بشكل متزامن. افتراضيا، هذه الطريقة لها مهلة زمنية تبلغ عشر ثوان وفترة استطلاع مدتها ثانية واحدة.

إليك مثال على دالة HTTP-trigger التي توضح كيفية استخدام هذه الواجهة:

نموذج العامل المعزول
[Function("HttpSyncStart")]
public static async Task<HttpResponseData> Run(
    [HttpTrigger(
        AuthorizationLevel.Function,
        "post",
        Route = "orchestrators/{functionName}/wait")] HttpRequestData request,
    [DurableClient] DurableTaskClient client,
    string functionName)
{
    string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(functionName);

    using var timeoutCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));
    return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(
        request,
        instanceId,
        timeoutCancellation.Token);
}

النموذج أثناء العملية
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

namespace VSSample
{
    public static class HttpSyncStart
    {
        private const string Timeout = "timeout";
        private const string RetryInterval = "retryInterval";

        [FunctionName("HttpSyncStart")]
        public static async Task<HttpResponseMessage> Run(
            [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}/wait")]
            HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            string functionName,
            ILogger log)
        {
            // Function input comes from the request content.
            object eventData = await req.Content.ReadAsAsync<object>();
            string instanceId = await starter.StartNewAsync(functionName, eventData);

            log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

            TimeSpan timeout = GetTimeSpan(req, Timeout) ?? TimeSpan.FromSeconds(30);
            TimeSpan retryInterval = GetTimeSpan(req, RetryInterval) ?? TimeSpan.FromSeconds(1);
            
            return await starter.WaitForCompletionOrCreateCheckStatusResponseAsync(
                req,
                instanceId,
                timeout,
                retryInterval);
        }

        private static TimeSpan? GetTimeSpan(HttpRequestMessage request, string queryParameterName)
        {
            string queryParameterStringValue = request.RequestUri.ParseQueryString()[queryParameterName];
            if (string.IsNullOrEmpty(queryParameterStringValue))
            {
                return null;
            }

            return TimeSpan.FromSeconds(double.Parse(queryParameterStringValue));
        }
    }
}

توفر مجموعات تطوير المهام المتطورة طريقة للانتظار حتى تنتهي التنسيق بشكل متزامن.

using Microsoft.DurableTask.Client;

// Wait for orchestration to complete with a timeout
OrchestrationMetadata metadata = await client.WaitForInstanceCompletionAsync(
    instanceId,
    timeout: TimeSpan.FromSeconds(30),
    getInputsAndOutputs: true);

if (metadata.RuntimeStatus == OrchestrationRuntimeStatus.Completed)
{
    Console.WriteLine($"Output: {metadata.SerializedOutput}");
}

استدعاء الدالة مع السطر التالي. استخدم ثانيتين للاستراحة و0.5 ثانية لفترة إعادة المحاولة:

curl -X POST "http://localhost:7071/orchestrators/E1_HelloSequence/wait?timeout=2&retryInterval=0.5"

ملحوظة

يفترض الأمر cURL أعلاه أن لديك دالة منسق تسمى E1_HelloSequence في مشروعك. بسبب كيفية كتابة دالة مشغل HTTP، يمكنك استبدالها باسم أي دالة منسق في مشروعك.

اعتمادا على الوقت اللازم للحصول على الاستجابة من حالة التوزيع الأوركسترالي، هناك حالتان:

  • تنتهي حالات التوزيع ضمن المهلة المحددة (في هذه الحالة ثانيتين)، ويكون الرد هو مخرج مثيل التوزيع الفعلي، الذي يتم تقديمه بشكل متزامن:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Thu, 14 Dec 2021 06:14:29 GMT
Transfer-Encoding: chunked

[
    "Hello Tokyo!",
    "Hello Seattle!",
    "Hello London!"
]
  • لا يمكن لحالات التنسيق أن تنتهي ضمن المهلة المحددة المحددة، والاستجابة هي الافتراضية الموصوفة في اكتشاف رابط رابط API:
HTTP/1.1 202 Accepted
Content-Type: application/json; charset=utf-8
Date: Thu, 14 Dec 2021 06:13:51 GMT
Location: http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177?taskHub={taskHub}&connection={connection}&code={systemKey}
Retry-After: 10
Transfer-Encoding: chunked

{
    "id": "d3b72dddefce4e758d92f4d411567177",
    "sendEventPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177/raiseEvent/{eventName}?taskHub={taskHub}&connection={connection}&code={systemKey}",
    "statusQueryGetUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177?taskHub={taskHub}&connection={connection}&code={systemKey}",
    "terminatePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177/terminate?reason={text}&taskHub={taskHub}&connection={connection}&code={systemKey}",
    "suspendPostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177/suspend?reason={text}&taskHub={taskHub}&connection={connection}&code={systemKey}",
    "resumePostUri": "http://localhost:7071/runtime/webhooks/durabletask/instances/d3b72dddefce4e758d92f4d411567177/resume?reason={text}&taskHub={taskHub}&connection={connection}&code={systemKey}"
}

ملحوظة

قد يختلف تنسيق عناوين webhook حسب النسخة التي تستخدمها من مضيف دالات Azure. المثال السابق هو لمضيف دالات Azure 3.0.

استرجاع روابط webhook لإدارة HTTP لمثيلات التنسيق

استخدم نظاما خارجيا لمراقبة أو رفع الأحداث إلى مستوى التنسيق. تتواصل الأنظمة الخارجية مع Durable Functions عبر عناوين webhook التي تشكل جزءا من الاستجابة الافتراضية الموصوفة في <اكتشاف رابط رابط واجهة برمجة التطبيقات <(API) c0>>. يمكن الوصول إلى روابط webhook بشكل برمجي باستخدام ربط عميل التنسيق. تحديدا، تحصل واجهة برمجة تطبيقات إنشاء إدارة HTTP على كائن قابل للتسلسل يحتوي على هذه الروابط الخاصة ب webhook.

تحتوي واجهة برمجة تطبيقات حمولة إدارة HTTP على معلمة واحدة:

  • معرف المثيل: المعرف الفريد للمثيل.

ترجع الأساليب كائنا بخصائص السلسلة التالية:

  • المعرف: معرف المثيل الخاص بالتزامن (يجب أن يكون هو نفس InstanceId الإدخال).
  • StatusQueryGetUri: عنوان URL لحالة مثيل التنسيق.
  • SendEventPostUri: عنوان URL "رفع الحدث" لمثيل التنسيق.
  • TerminatePostUri: عنوان URL "إنهاء" لمثيل التنسيق.
  • PurgeHistoryDeleteUri: عنوان URL "محفوظات التطهير" لمثيل التنسيق.
  • SuspendPostUri: رابط "تعليق" لحالة التوزيع الموسيقي.
  • ResumePostUri: رابط "resume" الخاص بنسخة التوزيع الموسيقي.

ترسل الدوال نسخا من هذه الكائنات إلى أنظمة خارجية لمراقبة أو رفع الأحداث على التنسيقات المقابلة، كما هو موضح في الأمثلة التالية.

نموذج العامل المعزول
[Function("SendInstanceInfo")]
[CosmosDBOutput(
    databaseName: "MonitorDB",
    containerName: "HttpManagementPayloads",
    Connection = "CosmosDBConnectionSetting")]
public static object SendInstanceInfo(
    [ActivityTrigger] TaskActivityContext context,
    [DurableClient] DurableTaskClient client)
{
    HttpManagementPayload payload = client.CreateHttpManagementPayload(context.InstanceId);

    // Send the payload to Azure Cosmos DB.
    return new { Payload = payload, id = context.InstanceId };
}

النموذج أثناء العملية
[FunctionName("SendInstanceInfo")]
public static void SendInstanceInfo(
    [ActivityTrigger] IDurableActivityContext ctx,
    [DurableClient] IDurableOrchestrationClient client,
    [CosmosDB(
        databaseName: "MonitorDB",
        containerName: "HttpManagementPayloads",
        Connection = "CosmosDBConnectionSetting")]out dynamic document)
{
    HttpManagementPayload payload = client.CreateHttpManagementPayload(ctx.InstanceId);

    // send the payload to Azure Cosmos DB
    document = new { Payload = payload, id = ctx.InstanceId };
}

أعد إلى الوراء نسخ التوزيع الموسيقي

إذا حدث فشل في التنسيق لسبب غير متوقع، أعد النسخة إلى حالة سليمة سابقا باستخدام واجهة برمجة تطبيقات مبنية لهذا الغرض.

ملحوظة

هذه الواجهة ليست بديلا عن سياسات معالجة الأخطاء وإعادة المحاولة بشكل صحيح. بل هو مخصص للاستخدام فقط في الحالات التي تفشل فيها حالات التوزيع لأسباب غير متوقعة. لا يمكن "إعادة التوزيع الموسيقية في حالات غير Failed (على سبيل المثال، Running، Pending، Terminated، أو Completed) إلى الوراء. لمزيد من المعلومات حول سياسات معالجة الأخطاء وإعادة المحاولة، راجع مقالة معالجة الأخطاء .

استخدم طريقة (.NET) أو (JavaScript) من طريقة ><ربط عميل التنسيق لإعادة التوزيع إلى حالة Running. تعيد هذه الطريقة أيضا تشغيل فشل تنفيذ النشاط أو التنسيق الفرعي الذي تسبب في فشل التنسيق.

على سبيل المثال، لنفترض أن لديك سير عمل يتضمن سلسلة من الموافقات البشرية. افترض أن سلسلة من وظائف النشاط أبلغت شخصا بأن موافقته مطلوبة وانتظرت حتى الرد في الوقت الحقيقي. بعد أن تتلقى جميع أنشطة الموافقة ردودا أو تتوقف عن الوقت، افترض أن نشاطا آخر فشل بسبب خطأ في تكوين التطبيق، مثل سلسلة سلسلة الاتصال غير صالحة. والنتيجة هي فشل التنسيق في عمق سير العمل. مع واجهة برمجة التطبيقات RewindAsync (.NET) أو rewind (JavaScript)، يمكن لمسؤول التطبيق إصلاح خطأ التكوين وإعادة التنسيق الفاشل إلى الحالة التي سبقت الفشل مباشرة. لا يلزم إعادة الموافقة على أي من خطوات التفاعل البشري، ويمكن الآن إكمال التنسيق بنجاح.

ملحوظة

لا تدعم ميزة الإرجاع إرجاع مثيلات التنسيق التي تستخدم مؤقتات دائمة.

نموذج العامل المعزول
[Function("RewindInstance")]
public static Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("rewind-queue")] string instanceId)
{
    string reason = "Orchestrator failed and needs to be revived.";
    return client.RewindInstanceAsync(instanceId, reason);
}

النموذج أثناء العملية
[FunctionName("RewindInstance")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("rewind-queue")] string instanceId)
{
    string reason = "Orchestrator failed and needs to be revived.";
    return client.RewindAsync(instanceId, reason);
}

using Microsoft.DurableTask.Client;

string reason = "Orchestrator failed and needs to be revived.";
await client.RewindInstanceAsync(instanceId, reason);

إعادة تشغيل نسخ التوزيع الموسيقي

إعادة تشغيل التوزيع الموسيقي تخلق نسخة جديدة باستخدام تاريخ نسخة تم تشغيلها سابقا. هذه الميزة مفيدة عندما ترغب في إعادة تشغيل توزيع أوركسترالي بنفس نمط الإدخال ومعرف المثال، مما يخلق تجربة جديدة مبنية على الأصل.

نموذج العامل المعزول
[Function("RestartInstance")]
public static Task<string?> Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("restart-queue")] string instanceId)
{
    return client.RestartAsync(instanceId, restartWithNewInstanceId: true);
}

النموذج أثناء العملية
[FunctionName("RestartInstance")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("restart-queue")] string instanceId)
{
    return client.RestartAsync(instanceId, restartWithNewInstanceId: true);
}

using Microsoft.DurableTask.Client;

// Restart an orchestration with a new instance ID
string newInstanceId = await client.RestartInstanceAsync(instanceId, restartWithNewInstanceId: true);
Console.WriteLine($"Restarted as new instance: {newInstanceId}");

// Restart an orchestration keeping the same instance ID
await client.RestartInstanceAsync(instanceId, restartWithNewInstanceId: false);

تاريخ نسخة التوزيع النقائي

لإزالة جميع البيانات المرتبطة بتنظيم التشغيل، قم بمسح سجل المشاهد. على سبيل المثال، احذف أي موارد تخزين مرتبطة بمثيل مكتمل. استخدم واجهة برمجة تطبيقات مثيل التطهير التي يحددها عميل التنسيق.

المثال التالي يوضح كيفية تطهير نسخة أوركسترا واحدة.

نموذج العامل المعزول
[Function("PurgeInstanceHistory")]
public static async Task Run(
    [DurableClient] DurableTaskClient client,
    [QueueTrigger("purge-queue")] string instanceId)
{
    await client.PurgeInstanceAsync(instanceId);
}

النموذج أثناء العملية
[FunctionName("PurgeInstanceHistory")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [QueueTrigger("purge-queue")] string instanceId)
{
    return client.PurgeInstanceHistoryAsync(instanceId);
}

using Microsoft.DurableTask.Client;

// Purge a single orchestration instance
PurgeResult result = await client.PurgeInstanceAsync(instanceId);
Console.WriteLine($"Purged {result.PurgedInstanceCount} instance(s).");

المثال التالي يظهر دالة يتم تفعيلها بالمؤقت تقوم بحذف السجل لجميع حالات التوزيع الموسيقي التي اكتملت بعد الفترة الزمنية المحددة. في هذه الحالة، فإنه يزيل البيانات لجميع المثيلات المكتملة منذ 30 يوما أو أكثر. تتم جدولة هذه الدالة على سبيل المثال للتشغيل مرة واحدة يوميا، في الساعة 12:00 مساء بالتوقيت العالمي المتفق عليه:

نموذج العامل المعزول
[Function("PurgeInstanceHistory")]
public static async Task Run(
    [DurableClient] DurableTaskClient client,
    [TimerTrigger("0 0 12 * * *")] TimerInfo myTimer)
{
    var filter = new PurgeInstancesFilter(
        CreatedFrom: DateTime.MinValue,
        CreatedTo: DateTime.UtcNow.AddDays(-30),
        Statuses: new[] { OrchestrationRuntimeStatus.Completed });

    await client.PurgeAllInstancesAsync(filter);
}

النموذج أثناء العملية
[FunctionName("PurgeInstanceHistory")]
public static Task Run(
    [DurableClient] IDurableOrchestrationClient client,
    [TimerTrigger("0 0 12 * * *")] TimerInfo myTimer)
{
    return client.PurgeInstanceHistoryAsync(
        DateTime.MinValue,
        DateTime.UtcNow.AddDays(-30),  
        new List<OrchestrationStatus>
        {
            OrchestrationStatus.Completed
        });
}

using Microsoft.DurableTask.Client;

// Purge completed instances older than 30 days
var filter = new PurgeInstancesFilter(
    CreatedFrom: DateTime.MinValue,
    CreatedTo: DateTime.UtcNow.AddDays(-30),
    Statuses: new[] { OrchestrationRuntimeStatus.Completed });

PurgeResult result = await client.PurgeAllInstancesAsync(filter);
Console.WriteLine($"Purged {result.PurgedInstanceCount} instance(s).");

ملحوظة

لكي تنجح عملية محفوظات الإزالة، يجب أن تكون حالة وقت التشغيل للمثيل الهدف مكتملة أو منتهية أو فاشلة.

الخطوات التالية