İşlevler için Azure SQL tetikleyicisi

Not

Tüketim planı işlevlerinde SQL tetikleyicisi için otomatik ölçeklendirme desteklenmez. Otomatik ölçeklendirme işlemi işlevi durdurursa, olayların tüm işlenmesi durdurulur ve el ile yeniden başlatılması gerekir.

SQL tetikleyicisi ile avantajları ölçeklendirmek için premium veya ayrılmış planları kullanın.

Azure SQL tetikleyicisi, sql tablosunu değişiklikler için izlemek ve satır oluşturulduğunda, güncelleştirildiğinde veya silindiğinde bir işlevi tetiklemek için SQL değişiklik izleme işlevini kullanır. Azure SQL tetikleyicisi ile kullanılmak üzere değişiklik izleme yapılandırma ayrıntıları için bkz . Değişiklik izlemeyi ayarlama. Azure İşlevleri için Azure SQL uzantısının kurulum ayrıntıları hakkında bilgi için bkz. SQL bağlamaya genel bakış.

Tüketim ve Premium planları için Azure SQL tetikleyicisi ölçeklendirme kararları hedef tabanlı ölçeklendirme yoluyla yapılır. Daha fazla bilgi için bkz . Hedef tabanlı ölçeklendirme.

İşlevselliğe Genel Bakış

Azure SQL tetikleyici bağlaması, değişiklikleri denetlemek için bir yoklama döngüsü kullanır ve değişiklikler algılandığında kullanıcı işlevini tetikler. Yüksek düzeyde döngü şöyle görünür:

while (true) {
    1. Get list of changes on table - up to a maximum number controlled by the Sql_Trigger_MaxBatchSize setting
    2. Trigger function with list of changes
    3. Wait for delay controlled by Sql_Trigger_PollingIntervalMs setting
}

Değişiklikler, değişiklik sırasına göre işlenir ve en eski değişiklikler önce işlenir. Değişiklik işleme hakkında birkaç not:

  1. Birden çok satırda yapılan değişiklikler aynı anda yapılırsa, bunların işleve gönderilme sırası CHANGETABLE işlevi tarafından döndürülen sırayı temel alır
  2. Değişiklikler bir satır için birlikte "toplu olarak" oluşturulur. Döngünün her yinelemesi arasında bir satırda birden çok değişiklik yapılırsa, bu satır için son işlenen durum ile geçerli durum arasındaki farkı gösteren tek bir değişiklik girişi vardır
  3. Bir satır kümesinde değişiklik yapılırsa ve aynı satırların yarısında başka bir değişiklik kümesi yapılırsa, ikinci kez değiştirilmeyen satırların yarısı önce işlenir. Bu işleme mantığının nedeni, yukarıdaki notta yapılan değişikliklerin toplu olarak işlenmesidir. Tetikleyici yalnızca yapılan "son" değişikliği görür ve bunu bunları işlenme sırası için kullanır

Değişiklik izleme ve Azure SQL tetikleyicileri gibi uygulamalar tarafından nasıl kullanıldığı hakkında daha fazla bilgi için bkz . Değişiklik izleme ile çalışma .

Örnek kullanım

GitHub deposunda Azure SQL tetikleyicisi için daha fazla örnek mevcuttur.

Örnek bir ToDoItem sınıfa ve buna karşılık gelen bir veritabanı tablosuna başvurur:

namespace AzureSQL.ToDo
{
    public class ToDoItem
    {
        public Guid Id { get; set; }
        public int? order { get; set; }
        public string title { get; set; }
        public string url { get; set; }
        public bool? completed { get; set; }
    }
}
CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

Değişiklik izleme , veritabanında ve tabloda etkinleştirilir:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL tetikleyicisi, her biri SqlChange iki özelliğe sahip nesnelerin bir listesine bağlanırIReadOnlyList<SqlChange<T>>:

  • Öğe: Değiştirilen öğe. Öğenin türü, sınıfında görüldüğü gibi tablo şemasını ToDoItem izlemelidir.
  • İşlem: sabit tablosundan SqlChangeOperation bir değer. Olası değerler: Insert, Update ve Delete.

Aşağıdaki örnekte, tabloda değişiklikler ToDo olduğunda çağrılan bir C# işlevi gösterilmektedir:

using System;
using System.Collections.Generic;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Sql;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;


namespace AzureSQL.ToDo
{
    public static class ToDoTrigger
    {
        [Function("ToDoTrigger")]
        public static void Run(
            [SqlTrigger("[dbo].[ToDo]", "SqlConnectionString")]
            IReadOnlyList<SqlChange<ToDoItem>> changes,
            FunctionContext context)
        {
            var logger = context.GetLogger("ToDoTrigger");
            foreach (SqlChange<ToDoItem> change in changes)
            {
                ToDoItem toDoItem = change.Item;
                logger.LogInformation($"Change operation: {change.Operation}");
                logger.LogInformation($"Id: {toDoItem.Id}, Title: {toDoItem.title}, Url: {toDoItem.url}, Completed: {toDoItem.completed}");
            }
        }
    }
}

Örnek kullanım

GitHub deposunda Azure SQL tetikleyicisi için daha fazla örnek mevcuttur.

Örnek bir ToDoItem sınıfa, sınıfa SqlChangeToDoItem , SqlChangeOperation sabit listesine ve buna karşılık gelen bir veritabanı tablosuna başvurur:

Ayrı bir dosyada ToDoItem.java:

package com.function;
import java.util.UUID;

public class ToDoItem {
    public UUID Id;
    public int order;
    public String title;
    public String url;
    public boolean completed;

    public ToDoItem() {
    }

    public ToDoItem(UUID Id, int order, String title, String url, boolean completed) {
        this.Id = Id;
        this.order = order;
        this.title = title;
        this.url = url;
        this.completed = completed;
    }
}

Ayrı bir dosyada SqlChangeToDoItem.java:

package com.function;

public class SqlChangeToDoItem {
    public ToDoItem item;
    public SqlChangeOperation operation;

    public SqlChangeToDoItem() {
    }

    public SqlChangeToDoItem(ToDoItem Item, SqlChangeOperation Operation) {
        this.Item = Item;
        this.Operation = Operation;
    }
}

Ayrı bir dosyada SqlChangeOperation.java:

package com.function;

import com.google.gson.annotations.SerializedName;

public enum SqlChangeOperation {
    @SerializedName("0")
    Insert,
    @SerializedName("1")
    Update,
    @SerializedName("2")
    Delete;
}
CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

Değişiklik izleme , veritabanında ve tabloda etkinleştirilir:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL tetikleyicisi, her biri SqlChangeToDoItem iki özelliğe sahip bir nesne dizisine bağlanırSqlChangeToDoItem[]:

  • item: değiştirilen öğe. Öğenin türü, sınıfında görüldüğü gibi tablo şemasını ToDoItem izlemelidir.
  • operation: enum'dan SqlChangeOperation bir değer. Olası değerler: Insert, Update ve Delete.

Aşağıdaki örnekte, tabloda değişiklikler ToDo olduğunda çağrılan bir Java işlevi gösterilmektedir:

package com.function;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.sql.annotation.SQLTrigger;
import com.function.Common.SqlChangeToDoItem;
import com.google.gson.Gson;

import java.util.logging.Level;

public class ProductsTrigger {
    @FunctionName("ToDoTrigger")
    public void run(
            @SQLTrigger(
                name = "todoItems",
                tableName = "[dbo].[ToDo]",
                connectionStringSetting = "SqlConnectionString")
                SqlChangeToDoItem[] todoItems,
            ExecutionContext context) {

        context.getLogger().log(Level.INFO, "SQL Changes: " + new Gson().toJson(changes));
    }
}

Örnek kullanım

GitHub deposunda Azure SQL tetikleyicisi için daha fazla örnek mevcuttur.

Örnek bir ToDoItem veritabanı tablosuna başvurur:

CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

Değişiklik izleme , veritabanında ve tabloda etkinleştirilir:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL tetikleyicisi, her biri iki özelliğe sahip nesnelerin listesini öğesine bağlar todoChanges:

  • item: değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: olası değerler , Updateve DeleteşeklindedirInsert.

Aşağıdaki örnekte, tabloda değişiklikler ToDo olduğunda çağrılan bir PowerShell işlevi gösterilmektedir.

Function.json dosyasındaki verileri bağlama aşağıdadır:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Yapılandırma bölümünde bu özellikler açıklanır.

Aşağıda, dosyadaki işlev için örnek PowerShell kodu verilmiştir run.ps1 :

using namespace System.Net

param($todoChanges)
# The output is used to inspect the trigger binding parameter in test methods.
# Use -Compress to remove new lines and spaces for testing purposes.
$changesJson = $todoChanges | ConvertTo-Json -Compress
Write-Host "SQL Changes: $changesJson"

Örnek kullanım

GitHub deposunda Azure SQL tetikleyicisi için daha fazla örnek mevcuttur.

Örnek bir ToDoItem veritabanı tablosuna başvurur:

CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

Değişiklik izleme , veritabanında ve tabloda etkinleştirilir:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL tetikleyicisi todoChanges, her biri iki özelliğe sahip bir nesne dizisi bağlar:

  • item: değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: olası değerler , Updateve DeleteşeklindedirInsert.

Aşağıdaki örnekte, tabloda değişiklikler ToDo olduğunda çağrılan bir JavaScript işlevi gösterilmektedir.

Function.json dosyasındaki verileri bağlama aşağıdadır:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Yapılandırma bölümünde bu özellikler açıklanır.

Aşağıda, dosyasındaki işlev için örnek JavaScript kodu verilmiştir index.js :

module.exports = async function (context, todoChanges) {
    context.log(`SQL Changes: ${JSON.stringify(todoChanges)}`)
}

Örnek kullanım

GitHub deposunda Azure SQL tetikleyicisi için daha fazla örnek mevcuttur.

Örnek bir ToDoItem veritabanı tablosuna başvurur:

CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);

Değişiklik izleme , veritabanında ve tabloda etkinleştirilir:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

SQL tetikleyicisi, her biri iki özelliğe sahip nesnelerin bir listesi olan bir değişkenine todoChangesbağlanır:

  • item: değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: olası değerler , Updateve DeleteşeklindedirInsert.

Aşağıdaki örnekte, tabloda değişiklikler ToDo olduğunda çağrılan bir Python işlevi gösterilmektedir.

Function.json dosyasındaki verileri bağlama aşağıdadır:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Yapılandırma bölümünde bu özellikler açıklanır.

Dosyadaki işlev için örnek Python kodu aşağıda verilmiştir __init__.py :

import json
import logging

def main(changes):
    logging.info("SQL Changes: %s", json.loads(changes))

Özellikler

C# kitaplığı, aşağıdaki özelliklere sahip olan işlevde SQL tetikleyicisini bildirmek için SqlTrigger özniteliğini kullanır:

Öznitelik özelliği Açıklama
TableName Gerekli. Tetikleyici tarafından izlenen tablonun adı.
Bağlan ionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesi içeren bir uygulama ayarının adı. bağlantı dizesi ayarı adı, Azure SQL veya SQL Server örneğine bağlantı dizesi içeren uygulama ayarına (local.settings.jsonyerel geliştirme için) karşılık gelir.
LeasesTableName isteğe bağlı. Kiralamaları depolamak için kullanılan tablonun adı. Belirtilmezse, kiralar tablosu adı Leases_{FunctionId}_{TableId} olur. Bunun nasıl oluşturulduğu hakkında daha fazla bilgiyi burada bulabilirsiniz.

Ek Açıklamalar

Java işlevleri çalışma zamanı kitaplığında, değeri Azure SQL'den gelen parametrelerde ek açıklamayı (com.microsoft.azure.functions.sql.annotation.SQLTrigger) kullanın@SQLTrigger. Bu ek açıklama aşağıdaki öğeleri destekler:

Öğe Açıklama
Adı Gerekli. Tetikleyicinin bağlandığını parametrenin adı.
Tablename Gerekli. Tetikleyici tarafından izlenen tablonun adı.
connectionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesi içeren bir uygulama ayarının adı. bağlantı dizesi ayarı adı, Azure SQL veya SQL Server örneğine bağlantı dizesi içeren uygulama ayarına (local.settings.jsonyerel geliştirme için) karşılık gelir.
LeasesTableName isteğe bağlı. Kiralamaları depolamak için kullanılan tablonun adı. Belirtilmezse, kiralar tablosu adı Leases_{FunctionId}_{TableId} olur. Bunun nasıl oluşturulduğu hakkında daha fazla bilgiyi burada bulabilirsiniz.

Yapılandırma

Aşağıdaki tabloda, function.json dosyasında ayarladığınız bağlama yapılandırma özellikleri açıklanmaktadır.

function.json özelliği Açıklama
Adı Gerekli. Tetikleyicinin bağlandığını parametrenin adı.
type Gerekli. olarak ayarlanmalıdır sqlTrigger.
direction Gerekli. olarak ayarlanmalıdır in.
Tablename Gerekli. Tetikleyici tarafından izlenen tablonun adı.
connectionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesi içeren bir uygulama ayarının adı. bağlantı dizesi ayarı adı, Azure SQL veya SQL Server örneğine bağlantı dizesi içeren uygulama ayarına (local.settings.jsonyerel geliştirme için) karşılık gelir.
LeasesTableName isteğe bağlı. Kiralamaları depolamak için kullanılan tablonun adı. Belirtilmezse, kiralar tablosu adı Leases_{FunctionId}_{TableId} olur. Bunun nasıl oluşturulduğu hakkında daha fazla bilgiyi burada bulabilirsiniz.

İsteğe Bağlı Yapılandırma

SQL tetikleyicisi için aşağıdaki isteğe bağlı ayarlar yapılandırılabilir:

Bu bölümde, 2.x ve üzeri sürümlerde bu bağlama için kullanılabilen yapılandırma ayarları açıklanmaktadır. host.json dosyasındaki Ayarlar bir işlev uygulaması örneğindeki tüm işlevlere uygulanır. Aşağıdaki örnek host.json dosyası, bu bağlama için yalnızca sürüm 2.x+ ayarlarını içerir. 2.x ve sonraki sürümlerdeki işlev uygulaması yapılandırma ayarları hakkında daha fazla bilgi için bkz. Azure İşlevleri için host.json başvuru.

Ayar Açıklama
Sql_Trigger_BatchSize Tetiklenen işleve gönderilmeden önce tetikleyici döngüsünün her yinelemesiyle işlenen en fazla değişiklik sayısı. Varsayılan değer 100 şeklindedir.
Sql_Trigger_PollingIntervalMs Her bir değişiklik toplu işleminin işlenmesi arasındaki milisaniye cinsinden gecikme. Varsayılan değer 1000 'dir (1 saniye).
Sql_Trigger_MaxChangesPerWorker Uygulama çalışanı başına izin verilen kullanıcı tablosundaki bekleyen değişikliklerin sayısıyla ilgili üst sınır. Değişiklik sayısı bu sınırı aşarsa ölçeği genişletmeye neden olabilir. Bu ayar yalnızca çalışma zamanı temelli ölçeklendirmenin etkinleştirildiği Azure İşlev Uygulamaları için geçerlidir. Varsayılan değer 1000'dir.

Değişiklik izlemeyi ayarlama (gerekli)

Azure SQL tetikleyicisiyle kullanılmak üzere değişiklik izlemenin ayarlanması için iki adım gerekir. Bu adımlar Visual Studio Code, Azure Data Studio veya SQL Server Management Studio gibi sorguları çalıştırmayı destekleyen tüm SQL araçlarından tamamlanabilir.

  1. İzlenecek tablonun bulunduğu veritabanının adıyla değiştirerek your database name SQL veritabanında değişiklik izlemeyi etkinleştirin:

    ALTER DATABASE [your database name]
    SET CHANGE_TRACKING = ON
    (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
    

    seçeneği, CHANGE_RETENTION değişiklik izleme bilgilerinin (değişiklik geçmişi) tutulduğu süreyi belirtir. Değişiklik geçmişinin SQL veritabanı tarafından saklanması tetikleyici işlevselliğini etkileyebilir. Örneğin, Azure İşlevi birkaç gün kapalıysa ve sonra sürdürülürse, veritabanı yukarıdaki kurulum örneğinde son iki gün içinde gerçekleşen değişiklikleri içerir.

    Bu AUTO_CLEANUP seçenek, eski değişiklik izleme bilgilerini kaldıran temizleme görevini etkinleştirmek veya devre dışı bırakmak için kullanılır. Tetikleyicinin çalışmasını engelleyen geçici bir sorun varsa, otomatik temizlemeyi kapatmak, sorun çözülene kadar saklama süresinden eski bilgilerin kaldırılmasını duraklatmak için yararlı olabilir.

    Değişiklik izleme seçenekleri hakkında daha fazla bilgiyi SQL belgelerinde bulabilirsiniz.

  2. İzlenecek tablonun adıyla değiştirerek your table name tabloda değişiklik izlemeyi etkinleştirin (uygunsa şemayı değiştirme):

    ALTER TABLE [dbo].[your table name]
    ENABLE CHANGE_TRACKING;
    

    Tetikleyicinin, değişiklikler için izlenen tabloda ve değişiklik izleme sistemi tablolarında okuma erişimine sahip olması gerekir. Her işlev tetikleyicisi ilişkili bir değişiklik izleme tablosuna sahiptir ve tabloyu bir şemada az_funckiralar. Bu tablolar henüz mevcut değilse tetikleyici tarafından oluşturulur. Bu veri yapıları hakkında daha fazla bilgiyi Azure SQL bağlama kitaplığı belgelerinde bulabilirsiniz.

Çalışma zamanı temelli ölçeklendirmeyi etkinleştirme

İsteğe bağlı olarak, işlevleriniz kullanıcı tablosunda işlenmeyi bekleyen değişikliklerin sayısına göre otomatik olarak ölçeklendirilebilir. SQL tetikleyicilerini kullanırken işlevlerinizin Premium planda düzgün ölçeklendirilmesine izin vermek için çalışma zamanı ölçeklendirme izlemeyi etkinleştirmeniz gerekir.

Azure portalında, işlev uygulamanızda Yapılandırma'yı seçin ve İşlev çalışma zamanı ayarları sekmesinde Çalışma zamanı ölçeği izlemeyi Açık duruma getirin.

Çalışma zamanı ölçeklendirmesini etkinleştirmek için Azure portal panelinin ekran görüntüsü.

Desteği yeniden deneyin

SQL tetikleyicisi yeniden deneme desteği ve kira tabloları hakkında daha fazla bilgiyi GitHub deposunda bulabilirsiniz.

Başlangıç yeniden denemeleri

Başlatma sırasında bir özel durum oluşursa, konak çalışma zamanı tetikleyici dinleyicisini üstel geri alma stratejisiyle otomatik olarak yeniden başlatmayı dener. Bu yeniden denemeler, dinleyici başarıyla başlatılana veya başlatma iptal edilene kadar devam eder.

Bağlantı yeniden denemeleri kesildi

İşlev başarıyla başlatılırsa ancak bir hata bağlantının bozulmasına (örneğin, sunucunun çevrimdışı olması) neden olursa işlev durdurulana veya bağlantı başarılı olana kadar bağlantıyı yeniden açmaya devam eder. Bağlantı başarıyla yeniden kurulursa kalan işlem değişikliklerini alır.

Bu yeniden denemelerin, SqlClient'ın sahip olduğu ve ConnectRetryIntervalbağlantı dizesi seçenekleriyle yapılandırılabilir yerleşik boşta bağlantı yeniden deneme mantığının ConnectRetryCount dışında olduğunu unutmayın. Önce yerleşik boşta bağlantı yeniden denemeleri denenir ve bunlar yeniden bağlanamazsa tetikleyici bağlaması bağlantıyı yeniden kurmaya çalışır.

İşlev özel durumu yeniden denemeleri

Değişiklikleri işlerken kullanıcı işlevinde bir özel durum oluşursa, şu anda işlenmekte olan satır toplu işlemi 60 saniye içinde yeniden denenir. Bu süre boyunca diğer değişiklikler normal şekilde işlenir, ancak özel duruma neden olan toplu işteki satırlar zaman aşımı süresi geçene kadar yoksayılır.

İşlev yürütmesi belirli bir satır için satırda beş kez başarısız olursa, bu satır gelecekteki tüm değişiklikler için tamamen yoksayılır. Toplu iş içindeki satırlar belirlenimci olmadığından, başarısız toplu iş içindeki satırlar sonraki çağrılarda farklı toplu işlerle sonuçlanabilir. Bu, başarısız toplu işteki tüm satırların mutlaka yoksayılmaması anlamına gelir. Özel duruma neden olan satırlar toplu işteki diğer satırlarsa, "iyi" satırlar gelecekteki çağrılarda başarısız olmayan farklı bir toplu işte sonuçlanabilir.

Sonraki adımlar