Funkcje zdefiniowane przez użytkownika w rejestrze poufnym Azure

Funkcje zdefiniowane przez użytkownika (UDF) w rejestrze poufnym Azure umożliwiają tworzenie niestandardowych funkcji języka JavaScript uruchamianych wewnątrz granicy zaufania rejestru. Ta funkcja jest prosta i łatwa w użyciu, dzięki czemu można rozszerzyć funkcjonalność interfejsu API rejestru bez konieczności tworzenia złożonych aplikacji. Funkcje zdefiniowane przez użytkownika były wcześniej nazywane prostymi funkcjami zdefiniowanymi przez użytkownika.

Za pomocą wbudowanego interfejsu API języka JavaScript można uruchamiać niestandardowy kod w celu wykonywania różnych zadań, takich jak zapytania niestandardowe i obliczenia, kontrole warunkowe, zadania przetwarzania końcowego i nie tylko. Ta funkcja jest odpowiednia w scenariuszach, w których potrzebna jest bezpośrednia integracja z istniejącym interfejsem API rejestru lub uruchamianie uproszczonej logiki niestandardowej w środowisku poufnym.

Aby uzyskać szybki przegląd i pokaz UDF, obejrzyj następujące wideo:

Uwaga / Notatka

Aby pracować z funkcjami zdefiniowanymi przez użytkownika, użyj wersji 2026-02-23 interfejsu API REST lub nowszej.

Wskazówka

Aby uzyskać bardziej zaawansowane scenariusze, takie jak niestandardowe Role-Based Access Control (RBAC) lub integracja z zewnętrznymi poufnymi obciążeniami roboczymi, zobacz punkty końcowe zdefiniowane przez użytkownika w Azure Confidential Ledger.

Przypadki użycia

Poufne funkcje użytkownika usługi rejestru platformy Azure umożliwiają rozszerzenie funkcjonalności rejestru poprzez uruchamianie logiki niestandardowej. Oto niektóre typowe zastosowania funkcji użytkownika:

  • Niestandardowe obliczenia i zapytania: uruchamiaj autonomiczne funkcje zdefiniowane przez użytkownika, aby odczytywać lub zapisywać dane w dowolnej tabeli aplikacji rejestru zgodnie z logiką biznesową.

  • Walidacja danych i kontrola danych wejściowych: używaj funkcji UDF jako kroków wstępnych, aby uruchamiać procesy wstępnego przetwarzania przed zapisaniem wpisu do rejestru, na przykład aby oczyścić dane wejściowe lub sprawdzić warunki wstępne.

  • Wzbogacanie danych i kontrakty inteligentne: użyj funkcji UDF jako wywołań następczych, aby uruchamiać akcje po zapisaniu wpisu w rejestrze, na przykład w celu dodania niestandardowych metadanych do rejestru lub wyzwalania przepływów pracy po zapisie.

Pisanie funkcji zdefiniowanych przez użytkownika (UDFs)

Poufna funkcja UDF rejestru Azure jest jednostką przechowywaną w rejestrze z unikatowym identyfikatorem i zawiera kod JavaScript, który jest wykonywany, gdy funkcja ta zostaje wywołana. W tej sekcji opisano sposób pisania kodu UDF i używania interfejsu API języka JavaScript do wykonywania różnych zadań.

Struktura funkcji

Kod funkcji zdefiniowanej przez użytkownika wymaga wyeksportowanej funkcji, która jest punktem wejścia skryptu w czasie wykonywania. Podstawowy szablon kodu UDF wygląda następująco:

export function main() {
    // Your JavaScript code here
}

Uwaga / Notatka

Nazwa wyeksportowanej funkcji punktu wejścia, która jest wywoływana podczas wykonywania, może zostać zmodyfikowana za pomocą argumentu exportedFunctionName podczas uruchamiania UDF. Jeśli nie zostanie określona, domyślna nazwa to main.

Uwaga / Notatka

Obsługiwane są funkcje lambda, ale wymagają jawnego zdefiniowania wyeksportowanych nazw funkcji i dopasowania jej do nazwy funkcji punktu wejścia. Przykład:

export const main = () => { 
    // Your JavaScript code here 
};

Argumenty funkcji

Możesz określić dowolne opcjonalne argumenty środowiska uruchomieniowego zaakceptowane przez funkcję zdefiniowanej przez użytkownika. Wartości argumentów można przekazać podczas uruchamiania funkcji zdefiniowanej przez użytkownika w czasie jej wykonywania, przy użyciu parametru arguments.

Argumenty są zawsze przekazywane jako tablica ciągów. Użytkownik jest odpowiedzialny za zapewnienie, że argumenty określone w kodzie UDF są zgodne z argumentami przekazanymi podczas uruchamiania UDF. Użytkownik powinien również upewnić się, że argumenty są prawidłowo parsowane do oczekiwanego typu danych w czasie wykonywania.

export function main(arg1, arg2) {
    // Your JavaScript code here
}

Interfejs API języka JavaScript

Kod JavaScript UDF jest wykonywany w środowisku piaskownicy, która zapewnia ograniczony zestaw interfejsów API.

Możesz użyć wszystkich standardowych funkcji globalnych, obiektów i wartości języka JavaScript. Można również użyć globalnego obiektu ccf, aby uzyskać dostęp do określonych funkcji i narzędzi udostępnianych przez platformę Confidential Consortium Framework (CCF), takich jak funkcje pomocnika kryptografii i akcesory tabel rejestru. Dokumentacja referencyjna interfejsu CCF dokumentuje pełny interfejs API obiektu globalnegoccf.

Dostęp do informacji kontekstowych bieżącego żądania można również uzyskać przy użyciu obiektu globalnego context . Ten obiekt zapewnia dostęp do metadanych żądania, które pochodzą z wykonania funkcji (context.request) i identyfikatora użytkownika obiektu wywołującego funkcję (context.userId). W przypadku hooków transakcji identyfikator kolekcji i zawartość transakcji powiązana z operacją zapisu są również dodawane do context obiektu (context.collectionId i context.contents odpowiednio).

Poniższy fragment kodu przedstawia kilka podstawowych przykładów użycia interfejsu API języka JavaScript:

export function main(args) {
    
    // Basic instructions
    const a = 1 + 1;

    // Basic statements
    if (a > 0) {
        console.log("a is positive");
    } else {
        console.log("a is negative or zero");
    }

    // Parse the string argument as a JSON object
    JSON.parse(args);

    // Logging utilities
    console.log("Hello world");
    
    // Math utilities
    Math.random();
    
    // CCF cryptography utilities
    ccf.crypto.digest("SHA-256", ccf.strToBuf("Hello world"));
    
    // Write to a custom ledger table
    ccf.kv["public:mytable"].set(ccf.strToBuf("myKey"), ccf.strToBuf("myValue"));

    // Read from a custom ledger table
    ccf.bufToStr(ccf.kv["public:mytable"].get(ccf.strToBuf("myKey")));

    // Read from the ledger entry table
    ccf.kv["public:confidentialledger.logs"].get(ccf.strToBuf("subledger:0"));

    // Get the request metadata that originated the function execution
    const requestMetadata = context.request;
    
    // Get the collection ID and transaction content (for transaction hooks only)
    const collectionId = context.collectionId;
    const contents = context.contents;

    // Throw exceptions
    throw new Error("MyCustomError");
}

Wskazówka

Aby uzyskać więcej informacji na temat sposobu użycia map rejestru do przechowywania i pobierania danych, zobacz dokumentację programu CCF dotyczącą interfejsu API magazynu Key-Value.

Uwaga / Notatka

Importowanie modułów nie jest obsługiwane w funkcjach zdefiniowanych przez użytkownika. Kod JavaScript musi być samodzielny i nie może polegać na zewnętrznych bibliotekach ani modułach. Internetowe interfejsy API również nie są obecnie obsługiwane.

Zarządzanie funkcjami zdefiniowanymi przez użytkownika

Aplikacje rejestru poufnego platformy Azure udostępniają dedykowany interfejs API CRUD do tworzenia, odczytywania, aktualizowania i usuwania jednostek UDF. Funkcje zdefiniowane przez użytkownika są bezpiecznie przechowywane w rejestrze i mogą być dostępne wyłącznie dla aplikacji rejestru.

Uwaga / Notatka

Funkcje zdefiniowane przez użytkownika i punkty końcowe zdefiniowane przez użytkownika (UDE) to wzajemnie wykluczające się funkcje. Nie można tworzyć ani uruchamiać funkcji zdefiniowanych przez użytkownika (UDF), jeśli zdefiniowano UDE, i na odwrót. Aby przełączyć się między nimi, postępuj zgodnie z instrukcjami w temacie Przełączanie między funkcjami zdefiniowanymi przez użytkownika i rozszerzeniami zdefiniowanymi przez użytkownika.

Tworzenie lub aktualizowanie funkcji zdefiniowanej przez użytkownika

PUT /app/userDefinedFunctions/myFunction
{
    "code": "export function main() { return 'Hello World'; }"
}

Ważne

Do utworzenia lub zaktualizowania UDF wymagana jest rola administratora.

Pobierz funkcję zdefiniowaną przez użytkownika

GET /app/userDefinedFunctions/myFunction

Lista funkcji zdefiniowanych przez użytkownika

GET /app/userDefinedFunctions

Usuń funkcję zdefiniowaną przez użytkownika

DELETE /app/userDefinedFunctions/myFunction

Ważne

Rola administratora jest wymagana do usunięcia funkcji zdefiniowanej przez użytkownika.

Uwaga / Notatka

Usunięcie funkcji zdefiniowanej przez użytkownika (UDF) powoduje, że jednostka zostaje usunięta tylko z aktualnego stanu rejestru. Każda usunięta funkcja zdefiniowana przez użytkownika jest zawsze zachowywana w historii niezmiennej księgi rozrachunkowej (jako każda zatwierdzona transakcja).

Limits

Azure confidential ledger ogranicza liczbę funkcji zdefiniowanych przez użytkownika w rejestrze, długość identyfikatorów UDF i rozmiar kodu UDF. Aby zapoznać się z bieżącymi limitami i sposobem ich wymuszania, zobacz Azure Confidential Ledger limits.

Uruchamianie funkcji zdefiniowanych przez użytkownika

Po utworzeniu poufnego rejestru platformy Azure użytkownicy mogą wykonywać funkcję zdefiniowaną przez użytkownika jako funkcję autonomiczną lub jako hak transakcji związany z operacją zapisu. Każde wykonanie funkcji zdefiniowanej przez użytkownika (UDF) jest uruchamiane w oddzielnym środowisku uruchomieniowym i sandboxie, co oznacza, że wykonanie UDF jest odizolowane od innych UDF-ów lub innych operacji rejestru.

Wykonywanie UDF można kontrolować przy użyciu opcjonalnych właściwości, które można określić wewnątrz żądania. Obecnie obsługiwane właściwości to:

  • arguments: tablica ciągów znaków, które reprezentują argumenty przekazywane do funkcji zdefiniowanej przez użytkownika (UDF). Argumenty są przekazywane w tej samej kolejności, w której są zdefiniowane w kodzie UDF. Wartość domyślna to pusta tablica.

  • exportedFunctionName: nazwa wyeksportowanej funkcji, która ma być wywoływana podczas wykonywania. Jeśli nie zostanie określony, wartość domyślna to main.

  • runtimeOptions: obiekt, który określa opcje środowiska uruchomieniowego dla wykonywania funkcji zdefiniowanej przez użytkownika, opisane w poniższej tabeli.

Option Description Domyślnie Dozwolone wartości
max_heap_bytes Maksymalny rozmiar sterty w bajtach. 104 857 600 (100 MiB) Rozmiar sterty jest obecnie stały na 100 MiB. Inne wartości tego nie zmieniają.
max_stack_bytes Maksymalny rozmiar stosu w bajtach. 1 048 576 (1 MiB) 1048 576 do 10 485 760 (10 MiB)
max_execution_time_ms Maksymalny czas wykonania w milisekundach. 5 000 (5 sekund) Od 5000 do 10 000 (10 sekund)
log_exception_details Czy rejestrować szczegóły wyjątku. false true lub false
return_exception_details Określa, czy w odpowiedzi mają być zwracane szczegóły wyjątku. true true lub false

Wartości poza dozwolonym zakresem nie powodują błędu. Zamiast tego rejestr używa najbliższej dozwolonej wartości.

Funkcje autonomiczne

Funkcja UDF może być wykonywana bezpośrednio przy użyciu interfejsu POST /app/userDefinedFunctions/{functionId}:execute API.

POST /app/userDefinedFunctions/myFunction:execute
{}

Treść żądania może służyć do określania opcjonalnych parametrów wykonywania, takich jak argumenty funkcji i właściwości środowiska uruchomieniowego języka JavaScript.

POST /app/userDefinedFunctions/myFunction:execute
{
    "arguments": ["arg1", "arg2"],
    "exportedFunctionName": "myMainFunction",
    "runtimeOptions": {
        "max_stack_bytes": 2097152,
        "max_execution_time_ms": 8000,
        "log_exception_details": true,
        "return_exception_details": true
    }
}

Odpowiedź wskazuje rezultat wykonania funkcji UDF (powiodło się lub nie powiodło się). Jeśli funkcja UDF powiodła się, odpowiedź zawiera wartość zwróconą przez funkcję w formacie tekstowym (jeśli istnieje).

{
    "result": 
        {
            "returnValue": "MyReturnValue"
        }, 
    "status": "Succeeded"
}

Jeśli funkcja zdefiniowana przez użytkownika nie powiodła się, odpowiedź zawiera komunikat o błędzie ze szczegółowym śladem stosu.

{
    "error": {
        "message": "Error while executing function myFunction: Error: MyCustomError\n    at myMainFunction (myFunction)\n"
    }, 
    "status": "Failed"
}

Ważne

Rola współautora jest wymagana do wykonania funkcji zdefiniowanej przez użytkownika.

Zaczepy transakcji

Funkcja UDF może być również wykonywana jako hak przedwstępny (pre-hook) lub jako hak końcowy (post-hook) po zapisaniu wpisu w księdze w ramach API zapisu księgi (POST /app/transactions). Hooki są uruchamiane w tym samym kontekście co operacja zapisu, co oznacza, że wszystkie dane zapisane w rejestrze przez hooki są automatycznie uwzględniane w tej samej transakcji zapisu.

Treść żądania zapisu może służyć do określenia dowolnych identyfikatorów UDF, które mają być wykonywane jako haki przednie i końcowe.

POST /app/transactions?collectionId=myCollection
{
  "contents": "myValue", 
  "preHooks": [ 
    { 
        "functionId": "myPreHook"
    } 
  ], 
  "postHooks": [ 
    { 
        "functionId": "myPostHook" 
    }
  ] 
} 

Ważne

Hooki muszą być jawnie zdefiniowane w treści żądania dla operacji zapisu. Ogólnie rzecz biorąc, funkcje zdefiniowane przez użytkownika nie mogą być uruchamiane automatycznie dla każdej operacji zapisu po utworzeniu.

Dla każdego haka można określić dowolne opcjonalne właściwości wykonywania. Przykład:

POST /app/transactions?collectionId=myCollection
{
  "contents": "myValue", 
  "preHooks": [ 
    { 
        "functionId": "myPreHook", 
        "properties": { 
            "arguments": [ 
                "arg1",
                "arg2"
            ], 
            "exportedFunctionName": "myMainFunction", 
            "runtimeOptions": { 
                "max_stack_bytes": 2097152,
                "max_execution_time_ms": 8000,
                "log_exception_details": true,
                "return_exception_details": true
            } 
        } 
    } 
  ], 
  "postHooks": [ 
    { 
        "functionId": "myPostHook", 
        "properties": { 
            "arguments": [ 
                "arg1"
            ], 
            "exportedFunctionName": "myMainFunction", 
            "runtimeOptions": { 
                "max_stack_bytes": 2097152,
                "max_execution_time_ms": 8000,
                "log_exception_details": true,
                "return_exception_details": true
            } 
        } 
    }
  ] 
} 

Hooki są zawsze wykonywane w kolejności, w jakiej są podane w treści żądania. Liczba wstępnych haków i końcowych haków w żądaniu jest ograniczona. Aby zapoznać się z bieżącymi limitami, zobacz limity usługi Azure Confidential Ledger.

W przypadku niepowodzenia przygotowania wstępnego lub kroku końcowego, cała transakcja zostanie przerwana. W takim przypadku odpowiedź zawiera komunikat o błędzie z przyczyną błędu:

{
    "error": {
        "code": "InternalError",
        "message": "Error while executing function myPreHook: Error: MyCustomError\n    at myMainFunction (myPreHook)\n"
    }
}

Uwaga / Notatka

Nawet jeśli wielokrotne hooki się powiodą, transakcja nadal może zakończyć się niepowodzeniem, jeśli którykolwiek ze zdefiniowanych pre-hooków lub post-hooków nie zostanie pomyślnie uruchomiony do ukończenia.

Wskazówka

Funkcja UDF może być ponownie użyta jako element wstępny i punkt zaczepienia w tym samym żądaniu i wywoływana wiele razy.

Przykłady

W tej sekcji przedstawiono kilka praktycznych przykładów używania funkcji zdefiniowanych przez użytkownika (UDF) w usłudze Azure Confidential Ledger. W poniższych przykładowych scenariuszach przyjęto założenie, że używasz usługi Azure Confidential Ledger do przechowywania transakcji bankowych różnych użytkowników banku.

Kontekst

Aby przechować transakcję bankową użytkownika, można użyć istniejącego interfejsu API do zapisu rejestru: wartość transakcji stanowi zawartość wpisu rejestru, a identyfikator użytkownika może być kolekcją lub kluczem, gdzie zawartość jest zapisywana.

POST /app/transactions?collectionId=John
{
    "contents": "10"
}

HTTP/1.1 200 OK

Ponieważ nie ma walidacji zawartości wejściowej, można zapisać wartość nieliczbową jako zawartość. Na przykład to żądanie powiedzie się, nawet jeśli wartość zawartości nie jest liczbą:

POST /app/transactions?collectionId=Mark
{
    "contents": "This is not a number"
}

HTTP/1.1 200 OK

Procedury wstępne na potrzeby walidacji danych

Aby upewnić się, że dane transakcji są zawsze liczbą, utwórz funkcję zdefiniowaną przez użytkownika, aby sprawdzić dane wejściowe. Poniższy pre-hook sprawdza, czy wartość zawartości jest liczbą, i zgłasza błąd, jeśli nią nie jest.

PUT /app/userDefinedFunctions/validateTransaction
{
    "code": "export function main() { if (isNaN(context.contents)) { throw new Error('Contents is not a number'); } }"
}

HTTP/1.1 201 CREATED

Za pomocą wstępnego haka w żądaniu zapisu można wymusić, że dane wejściowe odpowiadają oczekiwanemu formatowi. Poprzednie żądanie kończy się teraz niepowodzeniem zgodnie z oczekiwaniami:

POST /app/transactions?collectionId=Mark
{
    "contents": "This is not a number",
    "preHooks": [
        {
            "functionId": "validateTransaction"
        }
    ]
}

HTTP/1.1 500 INTERNAL_SERVER_ERROR
{
  "error": {
    "code": "InternalError",
    "message": "Error while executing function validateTransaction: Error: Contents is not a number\n    at main (validateTransaction)\n"
  }
}

Prawidłowe żądania zawierające wartości liczbowe zakończą się sukcesem zgodnie z oczekiwaniami.

POST /app/transactions?collectionId=Mark
{
    "contents": "30",
    "preHooks": [
        {
            "functionId": "validateTransaction"
        }
    ]
}

HTTP/1.1 200 OK

Post-hooks na potrzeby wzbogacania danych

Gdy użytkownicy wykonują nowe transakcje bankowe, chcemy rejestrować, gdy transakcja jest wyższa niż określony próg ze względów inspekcji. Element post-hook może służyć do zapisywania niestandardowych metadanych w rejestrze po operacji zapisu w celu wskazania, czy transakcja była wyższa niż określony próg.

Na przykład można utworzyć funkcję użytkownika w celu sprawdzenia wartości transakcji i zapisania fikcyjnego komunikatu ("Alert" dla wysokich wartości, "Normalny" w przeciwnym razie) przez użytkownika wprowadzającego do niestandardowej tabeli rejestru (payment_metadata), jeśli wartość jest większa niż 50.

PUT /app/userDefinedFunctions/detectHighTransaction
{
    "code": "export function main() { let value = 'Normal'; if (context.contents > 50) { value = 'Alert' } ccf.kv['public:payment_metadata'].set(ccf.strToBuf(context.collectionId), ccf.strToBuf(value)); }"
}

HTTP/1.1 201 CREATED

Po pomyślnym utworzeniu funkcji zdefiniowanej przez użytkownika można go użyć w nowych żądaniach zapisu:

POST /app/transactions?collectionId=Mark
{
    "contents": "100",
    "preHooks": [
        {
            "functionId": "validateTransaction"
        }
    ],
    "postHooks": [
        {
            "functionId": "detectHighTransaction"
        }
    ]
}

HTTP/1.1 200 OK
POST /app/transactions?collectionId=John
{
    "contents": "20",
    "preHooks": [
        {
            "functionId": "validateTransaction"
        }
    ],
    "postHooks": [
        {
            "functionId": "detectHighTransaction"
        }
    ]
}

HTTP/1.1 200 OK

Samodzielne funkcje zdefiniowane przez użytkownika dla niestandardowych kwerend

Aby sprawdzić najnowsze wartości zapisane w niestandardowej tabeli payment_metadata przy użyciu procedury post-hook, można utworzyć funkcję zdefiniowaną przez użytkownika w celu odczytania wartości z tabeli przy użyciu wejściowego identyfikatora użytkownika.

PUT /app/userDefinedFunctions/checkPaymentMetadataTable
{
    "code": "export function main(user) { const value = ccf.kv['public:payment_metadata'].get(ccf.strToBuf(user)); if (value === undefined) { throw new Error('UnknownUser'); } return ccf.bufToStr(value); }"
}

HTTP/1.1 201 CREATED

Dzięki bezpośredniemu uruchomieniu zdefiniowanej przez użytkownika funkcji (UDF) można sprawdzić najnowszą wartość zarejestrowaną w niestandardowej tabeli metadanych dla danego użytkownika.

W przypadku użytkowników z niedawną wysoką transakcją funkcja UDF zwraca wartość "Alert", jak oczekiwano.

POST /app/userDefinedFunctions/checkPaymentMetadataTable:execute
{
    "arguments": [
        "Mark"
    ]
}

HTTP/1.1 200 OK
{
  "result": {
    "returnValue": "Alert"
  },
  "status": "Succeeded"
}

W przypadku użytkowników z ostatnimi niskimi transakcjami funkcja UDF zwraca wartość "Normal" zamiast tego.

POST /app/userDefinedFunctions/checkPaymentMetadataTable:execute
{
    "arguments": [
        "John"
    ]
}

HTTP/1.1 200 OK
{
  "result": {
    "returnValue": "Normal"
  },
  "status": "Succeeded"
}

W przypadku użytkowników, którzy nie mają żadnego wpisu w tabeli niestandardowej, funkcja UDF zgłasza błąd zdefiniowany w kodzie UDF.

POST /app/userDefinedFunctions/checkPaymentMetadataTable:execute
{
    "arguments": [
        "Jane"
    ]
}

HTTP/1.1 200 OK
{
  "error": {
    "message": "Error while executing function checkPaymentMetadataTable: Error: UnknownUser\n    at main (checkPaymentMetadataTable)\n"
  },
  "status": "Failed"
}

Rozważania

  • Transakcyjne haki są obecnie obsługiwane tylko dla API POST /app/transactions podczas dodawania nowego wpisu do rejestru.

  • Funkcje zdefiniowane przez użytkownika i haki są zawsze wykonywane w podstawowej repliki rejestru, aby zapewnić kolejność transakcji i silną spójność.

  • Wykonywanie kodu UDF jest zawsze opakowane w jedną transakcję atomową. Jeśli logika języka JavaScript w UDF ukończy się bez żadnych wyjątków, wszystkie operacje w ramach UDF są zatwierdzane w rejestrze. Jeśli zostanie zgłoszony jakikolwiek wyjątek, wszystkie transakcje zostaną wycofane. Podobnie, pre-hooks i post-hooks są wykonywane w tym samym kontekście operacji zapisu, do której są zarejestrowane. Jeśli wstępny lub końcowy punkt kontroli zakończy się niepowodzeniem, cała transakcja zostanie przerwana i do rejestru nie zostanie dodany żaden wpis.

  • Ze względów bezpieczeństwa funkcje zdefiniowane przez użytkownika mogą uzyskiwać dostęp tylko do tabel aplikacji CCF i nie mogą uzyskiwać dostępu do wewnętrznych tabel księgi oraz tabel zarządzania ani innych wbudowanych tabel. Tabele rejestru, w których wpisy są zapisywane (public:confidentialledger.logs dla rejestrów publicznych i private:confidentialledger.logs prywatnych rejestrów) są tylko do odczytu.

  • Liczba pre-hooków i post-hooków, które można uruchomić w ramach pojedynczej transakcji zapisu, jest ograniczona. Aby zapoznać się z bieżącymi limitami, zobacz limity usługi Azure Confidential Ledger.

  • Opcja max_execution_time_ms środowiska uruchomieniowego ogranicza czas wykonywania funkcji zdefiniowanej przez użytkownika i hooka. Wartości domyślne i maksymalne opisano w Running UDFs. Jeśli funkcja działa dłużej niż limit, operacja zostanie przerwana i zostanie zwrócony błąd.