Dayanıklı İşlev düzenlemeleri kodda uygulanır ve programlama dilinin yerleşik hata işleme özelliklerini kullanabilir. Düzenlemelerinize hata işleme ve telafi eklemek için öğrenmeniz gereken yeni kavramlar yoktur. Ancak, bilmeniz gereken birkaç davranış vardır.
Not
Azure İşlevleri için Node.js programlama modelinin 4. sürümü genel olarak kullanılabilir. Yeni v4 modeli, JavaScript ve TypeScript geliştiricileri için daha esnek ve sezgisel bir deneyime sahip olacak şekilde tasarlanmıştır. Geçiş kılavuzunda v3 ve v4 arasındaki farklar hakkında daha fazla bilgi edinin.
Aşağıdaki kod parçacıklarında JavaScript (PM4), yeni deneyim olan programlama modeli V4'i belirtir.
Etkinlik işlevlerinde ve alt düzenlemelerde hatalar
Dayanıklı İşlevler'de, etkinlik işlevleri veya alt düzenlemelerde oluşan işlenmeyen özel durumlar, standartlaştırılmış özel durum türleri kullanılarak orchestrator işlevine geri sıralanır.
Örneğin, iki hesap arasında fon aktarımı gerçekleştiren aşağıdaki orchestrator işlevini göz önünde bulundurun:
Dayanıklı İşlevler C# süreç içi, işlenmeyen özel durumlar FunctionFailedException olarak fırlatılır.
Özel durum iletisi genellikle hataya hangi etkinlik işlevlerinin veya alt düzenlemelerin neden olduğunu tanımlar. Daha ayrıntılı hata bilgilerine erişmek için özelliğini inceleyin InnerException .
[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var transferDetails = context.GetInput<TransferOperation>();
await context.CallActivityAsync("DebitAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
try
{
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.DestinationAccount,
Amount = transferDetails.Amount
});
}
catch (FunctionFailedException)
{
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
}
}
Not
Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.
Dayanıklı İşlevler C# Yalıtılmış'da işlenmeyen özel durumlar TaskFailedException olarak gösterilir.
Özel durum iletisi genellikle hataya hangi etkinlik işlevlerinin veya alt düzenlemelerin neden olduğunu tanımlar. Daha ayrıntılı hata bilgilerine erişmek için FailureDetails özelliğini inceleyin.
[FunctionName("TransferFunds")]
public static async Task Run(
[OrchestrationTrigger] TaskOrchestrationContext context, TransferOperation transferDetails)
{
await context.CallActivityAsync("DebitAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
try
{
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.DestinationAccount,
Amount = transferDetails.Amount
});
}
catch (TaskFailedException)
{
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
}
}
Not
- Özel durum iletisi genellikle hataya hangi etkinlik işlevlerinin veya alt düzenlemelerin neden olduğunu tanımlar. Daha ayrıntılı hata bilgilerine erişmek için özelliğini inceleyin
FailureDetails .
- Varsayılan olarak,
FailureDetailshata türünü, hata iletisini, yığın izlemesini ve iç içe geçmiş iç özel durumları (her biri özyinelemeli FailureDetails nesne olarak temsil edilir) içerir. Hata çıkışına ek özel durum özellikleri eklemek istiyorsanız bkz. FailureDetails (.NET Yalıtılmış) için Özel Özel Durum Özellikleri Ekleme.
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const transferDetails = context.df.getInput();
yield context.df.callActivity("DebitAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
try {
yield context.df.callActivity("CreditAccount", {
account: transferDetails.destinationAccount,
amount: transferDetails.amount,
});
} catch (error) {
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
yield context.df.callActivity("CreditAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
}
})
const df = require("durable-functions");
df.app.orchestration("transferFunds", function* (context) {
const transferDetails = context.df.getInput();
yield context.df.callActivity("debitAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
try {
yield context.df.callActivity("creditAccount", {
account: transferDetails.destinationAccount,
amount: transferDetails.amount,
});
} catch (error) {
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
yield context.df.callActivity("creditAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
}
});
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
transfer_details = context.get_input()
yield context.call_activity('DebitAccount', {
'account': transfer_details['sourceAccount'],
'amount' : transfer_details['amount']
})
try:
yield context.call_activity('CreditAccount', {
'account': transfer_details['destinationAccount'],
'amount': transfer_details['amount'],
})
except:
yield context.call_activity('CreditAccount', {
'account': transfer_details['sourceAccount'],
'amount': transfer_details['amount']
})
main = df.Orchestrator.create(orchestrator_function)
Varsayılan olarak, PowerShell'deki cmdlet'ler try/catch blokları kullanılarak yakalanabilecek özel durumlar oluşturmaz. Bu davranışı değiştirmek için iki seçeneğiniz vardır:
-
-ErrorAction Stop gibi Invoke-DurableActivitycmdlet'leri çağırırken bayrağını kullanın.
-
$ErrorActionPreference Cmdlet'leri çağırmadan önce orchestrator işlevinde tercih değişkenini "Stop" olarak ayarlayın.
param($Context)
$ErrorActionPreference = "Stop"
$transferDetails = $Context.Input
Invoke-DurableActivity -FunctionName 'DebitAccount' -Input @{ account = transferDetails.sourceAccount; amount = transferDetails.amount }
try {
Invoke-DurableActivity -FunctionName 'CreditAccount' -Input @{ account = transferDetails.destinationAccount; amount = transferDetails.amount }
} catch {
Invoke-DurableActivity -FunctionName 'CreditAccount' -Input @{ account = transferDetails.sourceAccount; amount = transferDetails.amount }
}
PowerShell'de hata işleme hakkında daha fazla bilgi için Try-Catch-Finally PowerShell belgelerine bakın.
@FunctionName("TransferFunds")
public void transferFunds(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
TransferOperation transfer = ctx.getInput(TransferOperation.class);
ctx.callActivity(
"DebitAccount",
new OperationArgs(transfer.sourceAccount, transfer.amount)).await();
try {
ctx.callActivity(
"CreditAccount",
new OperationArgs(transfer.destinationAccount, transfer.amount)).await();
} catch (TaskFailedException ex) {
// Refund the source account on failure
ctx.callActivity(
"CreditAccount",
new OperationArgs(transfer.sourceAccount, transfer.amount)).await();
}
}
İlk CreditAccount işlev çağrısı başarısız olursa orchestrator işlevi, fonları kaynak hesaba geri yatırarak telafi eder.
Varlık işlevlerindeki hatalar
Varlık işlevleri için özel durum işleme davranışı Dayanıklı İşlevler barındırma modeline göre farklılık gösterir:
İşlemde C# kullanan Dayanıklı İşlevler'de, varlık işlevleri tarafından oluşan özgün özel durum türleri doğrudan düzenleyiciye döndürülür.
[FunctionName("Function1")]
public static async Task<string> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
try
{
var entityId = new EntityId(nameof(Counter), "myCounter");
await context.CallEntityAsync(entityId, "Add", 1);
}
catch (Exception ex)
{
// The exception type will be InvalidOperationException with the message "this is an entity exception".
}
return string.Empty;
}
[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
switch (ctx.OperationName.ToLowerInvariant())
{
case "add":
throw new InvalidOperationException("this is an entity exception");
case "get":
ctx.Return(ctx.GetState<int>());
break;
}
}
Dayanıklı İşlevler C# Yalıtılmış'da, özel durumlar orchestrator'a olarak EntityOperationFailedExceptiongösterilir. Özgün istisna ayrıntılarına ulaşmak için FailureDetails özelliğini inceleyin.
[Function(nameof(MyOrchestrator))]
public static async Task<List<string>> MyOrchestrator(
[Microsoft.Azure.Functions.Worker.OrchestrationTrigger] TaskOrchestrationContext context)
{
var entityId = new Microsoft.DurableTask.Entities.EntityInstanceId(nameof(Counter), "myCounter");
try
{
await context.Entities.CallEntityAsync(entityId, "Add", 1);
}
catch (EntityOperationFailedException ex)
{
// Add your error handling
}
return new List<string>();
}
df.app.orchestration("counterOrchestration", function* (context) {
const entityId = new df.EntityId(counterEntityName, "myCounter");
try {
const currentValue = yield context.df.callEntity(entityId, "get");
if (currentValue < 10) {
yield context.df.callEntity(entityId, "add", 1);
}
} catch (err) {
context.log(`Entity call failed: ${err.message ?? err}`);
}
});
df.app.orchestration("counterOrchestration", function* (context) {
const entityId = new df.EntityId(counterEntityName, "myCounter");
try {
const currentValue = yield context.df.callEntity(entityId, "get");
if (currentValue < 10) {
yield context.df.callEntity(entityId, "add", 1);
}
} catch (err) {
context.log(`Entity call failed: ${err.message ?? err}`);
}
});
@myApp.orchestration_trigger(context_name="context")
def run_orchestrator(context):
try:
entityId = df.EntityId("Counter", "myCounter")
yield context.call_entity(entityId, "get")
return "finished"
except Exception as e:
# Add your error handling
Varlık işlevleri şu anda PowerShell'de desteklenmiyor.
Varlık işlevleri şu anda Java'da desteklenmiyor.
Hatada otomatik yeniden deneme
Etkinlik işlevlerini veya alt düzenleme işlevlerini çağırdığınızda, otomatik bir yeniden deneme ilkesi belirtebilirsiniz. Aşağıdaki örnek, bir işlevi en fazla üç kez çağırmayı dener ve her yeniden deneme arasında 5 saniye bekler:
[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);
// ...
}
Not
Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.
[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
var options = TaskOptions.FromRetryPolicy(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5)));
await context.CallActivityAsync("FlakyFunction", options: options);
// ...
}
const df = require("durable-functions");
module.exports = df.orchestrator(function*(context) {
const firstRetryIntervalInMilliseconds = 5000;
const maxNumberOfAttempts = 3;
const retryOptions =
new df.RetryOptions(firstRetryIntervalInMilliseconds, maxNumberOfAttempts);
yield context.df.callActivityWithRetry("FlakyFunction", retryOptions);
// ...
});
const df = require("durable-functions");
df.app.orchestration("callActivityWithRetry", function* (context) {
const firstRetryIntervalInMilliseconds = 5000;
const maxNumberOfAttempts = 3;
const retryOptions = new df.RetryOptions(firstRetryIntervalInMilliseconds, maxNumberOfAttempts);
yield context.df.callActivityWithRetry("flakyFunction", retryOptions);
// ...
});
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
first_retry_interval_in_milliseconds = 5000
max_number_of_attempts = 3
retry_options = df.RetryOptions(first_retry_interval_in_milliseconds, max_number_of_attempts)
yield context.call_activity_with_retry('FlakyFunction', retry_options)
main = df.Orchestrator.create(orchestrator_function)
param($Context)
$retryOptions = New-DurableRetryOptions `
-FirstRetryInterval (New-TimeSpan -Seconds 5) `
-MaxNumberOfAttempts 3
Invoke-DurableActivity -FunctionName 'FlakyFunction' -RetryOptions $retryOptions
@FunctionName("TimerOrchestratorWithRetry")
public void timerOrchestratorWithRetry(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
final int maxAttempts = 3;
final Duration firstRetryInterval = Duration.ofSeconds(5);
RetryPolicy policy = new RetryPolicy(maxAttempts, firstRetryInterval);
TaskOptions options = new TaskOptions(policy);
ctx.callActivity("FlakeyFunction", options).await();
// ...
}
Önceki örnekteki etkinlik işlevi çağrısı, otomatik yeniden deneme ilkesini yapılandırmak için bir parametre alır. Otomatik yeniden deneme ilkesini özelleştirmek için çeşitli seçenekler vardır:
-
En fazla deneme sayısı: En fazla deneme sayısı. 1 olarak ayarlanırsa yeniden deneme olmaz.
-
İlk yeniden deneme aralığı: İlk yeniden deneme denemesi öncesinde bek süre.
-
Geri alma katsayısı: Geri alma artış oranını belirlemek için kullanılan katsayı. Varsayılan değer 1'tir.
-
En fazla yeniden deneme aralığı: Yeniden deneme denemeleri arasında bekleme süresi üst sınırı.
-
Yeniden deneme zaman aşımı: Yeniden denemeler yapmak için harcayacak maksimum süre. Varsayılan davranış, süresiz olarak yeniden denemektir.
Özel yeniden deneme işleyicileri
.NET veya Java kullanırken kodda yeniden deneme işleyicileri uygulama seçeneğiniz de vardır. Bildirim temelli yeniden deneme ilkeleri yeterince açıklayıcı olmadığında bu yararlı olur. Özel yeniden deneme işleyicilerini desteklemeyen diller için yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak yeniden deneme ilkeleri uygulama seçeneğiniz vardır.
RetryOptions retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: int.MaxValue)
{
Handle = exception =>
{
// True to handle and try again, false to not handle and throw.
if (exception is TaskFailedException failure)
{
// Exceptions from TaskActivities are always this type. Inspect the
// inner Exception to get more details.
}
return false;
};
}
await ctx.CallActivityWithRetryAsync("FlakeyActivity", retryOptions, null);
TaskOptions retryOptions = TaskOptions.FromRetryHandler(retryContext =>
{
// Don't retry anything that derives from ApplicationException
if (retryContext.LastFailure.IsCausedBy<ApplicationException>())
{
return false;
}
// Quit after N attempts
return retryContext.LastAttemptNumber < 3;
});
try
{
await ctx.CallActivityAsync("FlakeyActivity", options: retryOptions);
}
catch (TaskFailedException)
{
// Case when the retry handler returns false...
}
JavaScript şu anda özel yeniden deneme işleyicilerini desteklememektedir. Ancak yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak doğrudan orchestrator işlevinde yeniden deneme mantığını uygulama seçeneğiniz vardır.
JavaScript şu anda özel yeniden deneme işleyicilerini desteklememektedir. Ancak yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak doğrudan orchestrator işlevinde yeniden deneme mantığını uygulama seçeneğiniz vardır.
Python şu anda özel yeniden deneme işleyicilerini desteklememektedir. Ancak yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak doğrudan orchestrator işlevinde yeniden deneme mantığını uygulama seçeneğiniz vardır.
PowerShell şu anda özel yeniden deneme işleyicilerini desteklememektedir. Ancak yine de yeniden denemeler arasında gecikmeler eklemek için döngüleri, özel durum işlemeyi ve zamanlayıcıları kullanarak doğrudan orchestrator işlevinde yeniden deneme mantığını uygulama seçeneğiniz vardır.
RetryHandler retryHandler = retryCtx -> {
// Don't retry anything that derives from RuntimeException
if (retryCtx.getLastFailure().isCausedBy(RuntimeException.class)) {
return false;
}
// Quit after N attempts
return retryCtx.getLastAttemptNumber() < 3;
};
TaskOptions options = new TaskOptions(retryHandler);
try {
ctx.callActivity("FlakeyActivity", options).await();
} catch (TaskFailedException ex) {
// Case when the retry handler returns false...
}
İşlev zaman aşımları
Tamamlanması çok uzun sürüyorsa bir orchestrator işlevi içinde işlev çağrısını bırakmak isteyebilirsiniz. Bunu bugün gerçekleştirmenin doğru yolu, aşağıdaki örnekte olduğu gibi "herhangi bir " görev seçici ile dayanıklı bir zamanlayıcı oluşturmaktır:
[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
TimeSpan timeout = TimeSpan.FromSeconds(30);
DateTime deadline = context.CurrentUtcDateTime.Add(timeout);
using (var cts = new CancellationTokenSource())
{
Task activityTask = context.CallActivityAsync("FlakyFunction");
Task timeoutTask = context.CreateTimer(deadline, cts.Token);
Task winner = await Task.WhenAny(activityTask, timeoutTask);
if (winner == activityTask)
{
// success case
cts.Cancel();
return true;
}
else
{
// timeout case
return false;
}
}
}
Not
Önceki C# örnekleri Dayanıklı İşlevler 2.x içindir. Dayanıklı İşlevler 1.x için yerine DurableOrchestrationContextkullanmanız IDurableOrchestrationContext gerekir. Sürümler arasındaki farklar hakkında daha fazla bilgi için Dayanıklı İşlevler sürümleri makalesine bakın.
[Function("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
TimeSpan timeout = TimeSpan.FromSeconds(30);
DateTime deadline = context.CurrentUtcDateTime.Add(timeout);
using (var cts = new CancellationTokenSource())
{
Task activityTask = context.CallActivityAsync("FlakyFunction");
Task timeoutTask = context.CreateTimer(deadline, cts.Token);
Task winner = await Task.WhenAny(activityTask, timeoutTask);
if (winner == activityTask)
{
// success case
cts.Cancel();
return true;
}
else
{
// timeout case
return false;
}
}
}
const df = require("durable-functions");
const moment = require("moment");
module.exports = df.orchestrator(function*(context) {
const deadline = moment.utc(context.df.currentUtcDateTime).add(30, "s");
const activityTask = context.df.callActivity("FlakyFunction");
const timeoutTask = context.df.createTimer(deadline.toDate());
const winner = yield context.df.Task.any([activityTask, timeoutTask]);
if (winner === activityTask) {
// success case
timeoutTask.cancel();
return true;
} else {
// timeout case
return false;
}
});
const df = require("durable-functions");
const { DateTime } = require("luxon");
df.app.orchestration("timerOrchestrator", function* (context) {
const deadline = DateTime.fromJSDate(context.df.currentUtcDateTime).plus({ seconds: 30 });
const activityTask = context.df.callActivity("flakyFunction");
const timeoutTask = context.df.createTimer(deadline.toJSDate());
const winner = yield context.df.Task.any([activityTask, timeoutTask]);
if (winner === activityTask) {
// success case
timeoutTask.cancel();
return true;
} else {
// timeout case
return false;
}
});
import azure.functions as func
import azure.durable_functions as df
from datetime import datetime, timedelta
def orchestrator_function(context: df.DurableOrchestrationContext):
deadline = context.current_utc_datetime + timedelta(seconds = 30)
activity_task = context.call_activity('FlakyFunction')
timeout_task = context.create_timer(deadline)
winner = yield context.task_any(activity_task, timeout_task)
if winner == activity_task:
timeout_task.cancel()
return True
else:
return False
main = df.Orchestrator.create(orchestrator_function)
param($Context)
$expiryTime = New-TimeSpan -Seconds 30
$activityTask = Invoke-DurableActivity -FunctionName 'FlakyFunction'-NoWait
$timerTask = Start-DurableTimer -Duration $expiryTime -NoWait
$winner = Wait-DurableTask -Task @($activityTask, $timerTask) -NoWait
if ($winner -eq $activityTask) {
Stop-DurableTimerTask -Task $timerTask
return $True
}
else {
return $False
}
@FunctionName("TimerOrchestrator")
public boolean timerOrchestrator(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
Task<Void> activityTask = ctx.callActivity("SlowFunction");
Task<Void> timeoutTask = ctx.createTimer(Duration.ofMinutes(30));
Task<?> winner = ctx.anyOf(activityTask, timeoutTask).await();
if (winner == activityTask) {
// success case
return true;
} else {
// timeout case
return false;
}
}
Not
Bu mekanizma aslında devam eden etkinlik işlevi yürütmesini sonlandırmaz. Bunun yerine, orchestrator işlevinin sonucu yoksaymasına ve devam etmesine olanak tanır. Daha fazla bilgi için Zamanlayıcılar belgelerine bakın.
İşlenmeyen özel durumlar
Orchestrator işlevi işlenmeyen bir özel durumla başarısız olursa, özel durumun ayrıntıları günlüğe kaydedilir ve örnek bir Failed durumla tamamlar.
FailureDetails için Özel Durum Özellikleri Ekle (.NET Yalıtılmış)
.NET Yalıtılmış modelinde Dayanıklı Görev iş akışları çalıştırılırken, görev hataları otomatik olarak failureDetails nesnesine serileştirilir. Varsayılan olarak, bu nesne aşağıdaki gibi standart alanları içerir:
- ErrorType — özel durum türü adı
- İleti — özel durum iletisi
- StackTrace — serileştirilmiş yığın izlemesi
- InnerFailure – özyinelemeli iç özel durumlar için iç içe bir FailureDetails nesnesi
Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0'dan başlayarak, bir IExceptionPropertiesProvider ( v1.16.1paketinden başlayarak Microsoft.DurableTask.Worker'da tanımlanır) uygulayarak bu davranışı genişletebilirsiniz. Bu sağlayıcı, FailureDetails.Properties sözlüğüne hangi özel durum türlerinin ve hangi özelliklerinin dahil edilmesi gerektiğini tanımlar.
Not
- Bu özellik yalnızca .NET Yalıtılmış'da kullanılabilir. Java desteği gelecek bir sürümde eklenecektir.
-
Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0 veya üzerini kullandığınızdan emin olun.
-
Microsoft.DurableTask.Worker v1.16.1 veya üzerini kullandığınızdan emin olun.
Özel Durum Özellikleri Sağlayıcısını Gerçekleştirmek
Önemsediğiniz özel durumlar için seçili özellikleri ayıklamak ve döndürmek için özel bir IExceptionPropertiesProvider uygulayın. Eşleşen bir özel durum türü oluşturulduğunda döndürülen sözlük FailureDetails'in Özellikler alanında serileştirilir.
using Microsoft.DurableTask.Worker;
public class CustomExceptionPropertiesProvider : IExceptionPropertiesProvider
{
public IDictionary<string, object?>? GetExceptionProperties(Exception exception)
{
return exception switch
{
ArgumentOutOfRangeException e => new Dictionary<string, object?>
{
["ParamName"] = e.ParamName,
["ActualValue"] = e.ActualValue
},
InvalidOperationException e => new Dictionary<string, object?>
{
["CustomHint"] = "Invalid operation occurred",
["TimestampUtc"] = DateTime.UtcNow
},
_ => null // Other exception types not handled
};
}
}
Sağlayıcıyı Kaydetme
Özel IExceptionPropertiesProvider'ınızı .NET Yalıtılmış çalışan konağınıza( genellikle Program.cs) kaydedin:
using Microsoft.DurableTask.Worker;
using Microsoft.Extensions.DependencyInjection;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(builder =>
{
// Register custom exception properties provider
builder.Services.AddSingleton<IExceptionPropertiesProvider, CustomExceptionPropertiesProvider>();
})
.Build();
host.Run();
Kaydedildikten sonra, işlenen türlerden biriyle eşleşen herhangi bir özel durum, yapılandırılan özellikleri FailureDetails'e otomatik olarak ekler.
Örnek Hata Detayları Çıkışı
Sağlayıcınızın yapılandırmasıyla eşleşen bir özel durum oluştuğunda, düzenleme aşağıdaki gibi serileştirilmiş bir FailureDetails yapısı alır:
{
"errorType": "TaskFailedException",
"message": "Activity failed with an exception.",
"stackTrace": "...",
"innerFailure": {
"errorType": "ArgumentOutOfRangeException",
"message": "Specified argument was out of range.",
"properties": {
"ParamName": "count",
"ActualValue": 42
}
}
}
Sonraki adımlar