Bewerken

Delen via


Gridwich-aanvraagantwoordberichten

Azure Logic Apps
Azure Storage

In dit artikel worden de specifieke Event Grid-gebeurtenissen beschreven die de aanvraag-antwoordvolgorde vormen voor verschillende Gridwich-bewerkingen.

Gridwich-gebeurtenissen

Gridwich-bevestiging en Gridwich-fout verschillen van andere Gridwich-gebeurtenissen. Specifiek:

  • Gridwich-bevestiging (ACK) geeft aan dat Gridwich de aanvraag heeft ontvangen, maar niet noodzakelijkerwijs verwerkt, in een Request-ACK-Response-reeks.
  • Elke bewerking heeft een of meer unieke geslaagde responsgebeurtenissen, maar bijna alle bewerkingen gebruiken dezelfde gridwich-foutgebeurtenis om een fout te communiceren.

Coderingsgebeurtenissen

Blob- en containeropslag-gebeurtenissen

Opslagsleutels

Bewerkingscontext

Gridwich accepteert een JSON-object operationContext als onderdeel van aanvraagberichten. In het algemeen echot Gridwich een bijbehorend object in antwoordberichten en houdt zich niet bezig met de specifieke interne structuur of inhoud van het contextobject.

De uitzondering is dat het contextobject van het antwoord mogelijk extra JSON-eigenschappen heeft in vergelijking met het aanvraagequivalent. Deze extra eigenschappen zijn intern voor Gridwich en hun namen beginnen altijd met het tilde ~ teken. De aanvraageigenschappen zijn altijd aanwezig op het antwoordcontextobject.

Net als in normale JSON worden de eigenschappen van het antwoordobject in een andere volgorde weergegeven dan in het aanvraagobject.

Zie het artikel Bewerkingscontext in het artikel Gridwich Architecture voor meer informatie over de bewerkingscontext.

Event Grid-berichten

Zie de aanvraagstroom van de architectuur voor meer informatie over de berichtstroom voor aanvraagantwoorden.

In de volgende gebeurtenisbeschrijvingen zijn de JSON-eigenschapswaarden de gebruikelijke tekenreeks, het getal of de booleaanse typen. In de beschrijvingen worden de volgende specifieke tekenreeksinhoudstypen gebruikt. Als de beschrijving 'ondoorzichtig' bevat, zijn de inhoud en indeling van de waarde willekeurig.

  • GUID-string, zoals "b621f33d-d01e-0002-7ae5-4008f006664e" een 16-byte-id-waarde die is gespeld tot 36 tekens (32 hexe cijfers, plus 4 streepjes). Let op het gebrek aan accolades. De waarde is niet hoofdlettergevoelig. Deze indeling komt overeen met het resultaat van System.GUID.ToString("D").
  • Topic-stringis een "/subscriptions/5edeadbe-ef64-4022-a3aa-133bfef1d7a2/resourceGroups/gws-shared-rg-sb/providers/Microsoft.EventGrid/topics/gws-gws-egt-sb"tekenreeks met ondoorzichtige inhoud.
  • Subject-stringis een "/blobServices/default/containers/telestreamoutput/blobs/db08122195b66be71db9e54ae04c58df/503220533TAGHD23976fps16x990266772067587.mxf"tekenreeks met ondoorzichtige inhoud.
  • EventType-string, zoals "request.operation.requested" in het algemeen een tekenreeks van het formulier is: {"request"|"response"}.operation[.qualifier].
  • DataVersion-string, zoals "1.0", is een versiebeheerindicator die berichtprocessors gebruiken om verschillende evoluties van dezelfde bewerking te onderscheiden. Gridwich vereist dit veld. De HandlesEvent methode bepaalt welke versies een afzonderlijke Event Grid-handler kan verwerken.
  • URL-string is een absolute URL die vaak verwijst naar Application Insights-logboeken. Deze tekenreeksen zijn meestal een SAS-URL, vanwege vereisten voor doelautorisatie.
  • StorageURL-string is een absolute URL die vaak verwijst naar een Azure Storage-blob of -container. Deze tekenreeks is meestal geen SAS-URL.
  • StorageURL-SAS-string is een absolute SAS-URL die vaak verwijst naar een Azure Storage-blob of container.
  • OperationContextObject, zoals { "prodID": 10, "dc": "abc" }, is een willekeurig JSON-object dat wordt geaccepteerd voor binnenkomende aanvragen en wordt herhaald als onderdeel van Gridwich-antwoordgebeurtenissen.
  • Metadata-Dictionary is een JSON-objectwoordenlijst met tekenreeks-naar-tekenreeksen met de naam-waardeparen die azure Storage Blob-metagegevens vertegenwoordigen.
  • Encoder-Context is een ondoorzichtig JSON-object met eigenschappen die specifiek zijn voor een bepaalde encoder.

Gridwich generic ACK-antwoord

Gridwich>Requester, maakt gebruik van ResponseAcknowledgeDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "eventType": "request.blob.metadata.create"
    },
    "eventType": "response.acknowledge"
}

De data.eventType tekenreekswaarde is de eigenschap op het hoogste niveau eventType van de gebeurtenis Aanvraag. Voor een blobanalyseaanvraag isrequest.blob.analysis.create de data.eventType tekenreekswaarde bijvoorbeeld.

Gridwich generic Failure response

Gridwich>Requester, maakt gebruik van ResponseFailureDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "logEventId": 30001,
        "logEventMessage": "the message text for eventId 30001",
        "logRecordId": "GUID-string",
        "logRecordUrl": "URL-string", // AppInsight URL to the logRecordId
        "eventHandlerClassName": "string",
        "handlerId": "GUID-string"
    },
    "eventType": "response.failure"
}

De foutgebeurtenis bevat niet de oorspronkelijke aanvraagwaarde eventType , maar bevat wel de bewerkingscontext en de naam van de handler die de aanvraag heeft verwerkt. De log* eigenschappen hebben betrekking op de probleemgegevens die door het geconfigureerde Application Insights-exemplaar zijn vastgelegd.

Voor een beperkte set bewerkingen verschilt het gebeurtenisobject Fout aanzienlijk van het voorgaande bericht. Zie Opslagsleutels rollen voor meer informatie.

Aanvrager vraagt Gridwich om bepaalde metagegevens op een blob te plaatsen

Requester>Gridwich maakt gebruik van RequestBlobMetadataCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "blobMetadata": <Metadata-Dictionary>
    },
    "eventType": "request.blob.metadata.create"
}

Het blobMetadata is een object van eigenschappen met tekenreekswaarden die alle naam-waardeparen van de gewenste blobmetagegevens vertegenwoordigen.

Gridwich>Requester maakt gebruik van ResponseBlobMetadataSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "blobMetadata": <Metadata-Dictionary>
    },
    "eventType": "response.blob.metadata.success"
}

Als u de huidige metagegevens voor een blob later wilt ophalen, raadpleegt u de aanvraag Blob analyseren.

Aanvrager vraagt Gridwich om een analyse van een blob uit te voeren via MediaInfo

Requester>Gridwich maakt gebruik van RequestBlobAnalysisCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "analyzerSpecificData": {
            "mediaInfo": {
                  "commandLineOptions": {
                    "Complete": "1",
                    "Output": "JSON"
                  }
            }
        }
    },
    "eventType": "request.blob.analysis.create"
}

Gridwich>Requester maakt gebruik van ResponseBlobAnalysisSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "blobMetadata": <Metadata-Dictionary>,
        "analysisResults": <Analysis-Result-Object>
    },
    "eventType": "response.blob.analysis.success"
}

De inhoud van het analysisResults object is niet opgegeven. In het huidige project is dit de MediaInfo-uitvoer.

De blobMetadata waarde is een tekenreekswoordenlijst.object > van eigenschappen met tekenreekswaarden die alle naam-waardeparen van de metagegevens van de opgegeven blob vertegenwoordigen.

Zoals gebruikelijk bij Azure Storage moeten namen van metagegevensitems voldoen aan de naamgevingsregels voor C#-id's. Zie de Azure SetBlobMetadata REST API en de C#-naamgevingsregels voor meer informatie.

Aanvrager vraagt Gridwich om een blob naar een nieuwe bestemming te kopiëren

Requester>Gridwich maakt gebruik van RequestBlobCopyDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "sourceUri": "StorageURL-string",
        "destinationUri": "StorageURL-string"
    },
    "eventType": "request.blob.copy"
}

Gridwich>Requester maakt gebruik van ResponseBlobCopyScheduledDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "sourceUri": "URL-string",
        "blobMetadata": <Metadata-Dictionary>,
        "destinationUri": "StorageURL-string"
    },
    "eventType": "response.blob.copy.scheduled"
}

Gridwich vertelt aanvrager dat er een blob is gemaakt

Gridwich kan de blob hebben gemaakt op basis van elke bron, zoals een kopieerresultaat, postvak IN-aankomst of codeerresultaat.

Gridwich>Requester, maakt gebruik van ResponseBlobCreatedSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "blobMetadata": <Metadata-Dictionary>
    },
    "eventType": "response.blob.created.success"
}

Aanvrager vraagt Gridwich om een blob te verwijderen

Requester>Gridwich maakt gebruik van RequestBlobDeleteDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
    },
    "eventType": "request.blob.delete"
}

Gridwich>Requester maakt gebruik van ResponseBlobDeleteScheduledDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "blobMetadata": <Metadata-Dictionary>
    },
    "eventType": "response.blob.delete.scheduled"
}

Gridwich informeert aanvrager dat een blob is verwijderd

De blobverwijdering kan afkomstig zijn van elke bron, zoals een expliciete aanvraag van een aanvrager of een resultaat van interne bewerkingen.

Gridwich>Requester, maakt gebruik van ResponseBlobDeleteSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string"
    },
    "eventType": "response.blob.delete.success"
}

Aanvrager vraagt Gridwich om een SAS-URL voor de tijdverlooptijd te retourneren

Requester>Gridwich maakt gebruik van RequestBlobSasUrlCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "secToLive": 1200
    },
    "eventType": "request.blob.sas-url.create"
}

Gridwich>Requester maakt gebruik van ResponseBlobSasUrlSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "sasUrl": "StorageURL-SAS-string"
    },
    "eventType": "response.blob.sas-url.success"
}

Aanvrager vraagt Gridwich om te coderen via CloudPort Workflow

Requester>Gridwich, maakt gebruik van RequestCloudPortEncodeCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
          "inputs": [
                {"blobUri": "StorageURL-string" }
          ],
          "outputContainer": "https://<storageaccountname>.blob.core.windows.net/<containername>/",
          "workflowName": "TestWorkflow2",
          "parameters": [ { "prop1": "value1" } ],
           "secToLive": 18000
  },
  "eventType": "request.encode.cloudport.create",
}

Aanvrager vraagt Gridwich te coderen via Flip

Requester>Gridwich, maakt gebruik van RequestFlipEncodeCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
          "inputs": [
                {"blobUri": "StorageURL-string" }
          ],
          "outputContainer": "StorageURL-string", // of the Storage container
          "factoryName": "gws-dev-flip",
          "profiles": "h264",
          "parameters": [ { "prop1": "value1" } ],
           "secToLive": 18000
      },
      "eventType": "request.encode.flip.create"
}

Voorbeeld van RequestFlipEncodeCreateDTO

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": { "progId": 1234 },
          "inputs": [
            {
                "blobUri": "https://gws-sa1.blob.core.windows.net/Vid0001Container/input.mp4"
            }
          ],
          "outputContainer": "https://gws-sa22out.blob.core.windows.net/Out0004/",
          "factoryName": "gws-dev-flip",
          "profiles": "h264",
          "parameters": [ { "someProperty1": "someValue1" } ],
          "secToLive": 18000
      },
      "eventType": "request.encode.flip.create"
}

Gridwich-encoders veelvoorkomende aanvraag geslaagde verzendingsreactie

Gridwich>Requester, maakt gebruik van ResponseEncodeDispatchedDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "encoderContext": <EncoderContext>,
        "workflowJobName": "CloudPort or Flip assigned job name for workflow instance."
    },
    "eventType": "response.encode.<encodername>.dispatched"
}

De <encodername> is een van cloudport of flip.

Asynchrone statusberichten van gridwich-encoder

De Gridwich-encoders genereren vier soorten gebeurtenissen tijdens of aan het einde van de codering:

  • Scheduled
  • Verwerken
  • Geslaagd
  • Geannuleerd

Een codeeraanvraagfout genereert een gridwich-foutgebeurtenis.

Geplande coderingsstatus

Gridwich>Requester, maakt gebruik van ResponseEncodeScheduledDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "encoderContext":  <EncoderContext>,
        "workflowJobName": "CloudPort or Flip assigned job name for workflow instance."
    },
    "eventType": "response.encode.<encodername>.scheduled"
}

Verwerking van de coderingsstatus

Gridwich>Requester, maakt gebruik van ResponseEncodeProcessingDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "encoderContext": <EncoderContext>,
        "workflowJobName": "CloudPort or Flip assigned job name for workflow instance.",
        "currentStatus": "string",
        "percentComplete": 50,
    },
    "eventType": "response.encode.<encodername>.processing"
}

Geslaagde coderingsstatus

Gridwich>Requester, maakt gebruik van ResponseEncodeSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,,
        "encoderContext": <EncoderContext>,
        "workflowJobName": "CloudPort or Flip assigned job name for workflow instance.",
        "outputs":[
            { "blobUri": "StorageURL-string" }
        ]
    },
    "eventType": "response.encode.<encodername>.success"
}

De coderingsstatus is geannuleerd

Gridwich>Requester, maakt gebruik van ResponseEncodeCanceledDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "encoderContext": <EncoderContext>,
        "workflowJobName": "CloudPort or Flip assigned job name for workflow instance."
    },
    "eventType": "response.encode.<encodername>.canceled"
}

Aanvrager vraagt Gridwich om de opslaglaag van een blob te wijzigen

Requester>Gridwich maakt gebruik van RequestBlobTierChangeDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "accessTier": "string",
        "rehydratePriority": "string"
    },
    "eventType": "request.blob.tier.change"
}
  • De accessTier eigenschap is Hot, Coolof Archive.
  • De rehydratePriority eigenschap is Standard of High.

Gridwich>Requester maakt gebruik van ResponseBlobTierChangeSuccessDTO

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "blobUri": "StorageURL-string",
        "accessTier": "string",
        "rehydratePriority": "string"
    },
    "eventType":"response.blob.tier.success"
}

Aanvrager vraagt Gridwich om een blobcontainer te maken

De aanvraag biedt de naam van het opslagaccount en de container.

Requester>Gridwich maakt gebruik van RequestContainerCreateDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string", // e.g. mySA1
        "containerName": "string"       // e.g. mycontainer
    },
    "eventType": "request.blob.container.create"
}

Gridwich>Requester maakt gebruik van ResponseContainerCreatedSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string",
        "containerName": "string"
    },
    "eventType": "response.blob.container.create.success"
}

Aanvrager vraagt Gridwich om een blobcontainer te verwijderen

De aanvraag biedt de naam van het opslagaccount en de container.

Requester>Gridwich maakt gebruik van RequestContainerDeleteDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string",
        "containerName": "string"
    },
    "eventType": "request.blob.container.delete"
}

Gridwich>Requester maakt gebruik van ResponseContainerDeleteSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string",
        "containerName": "string"
    },
    "eventType": "response.blob.container.delete.success"
}

Aanvrager vraagt Gridwich om de openbare toegang van een container te wijzigen

De aanvraag geeft de containernaam en een accessType van Blob, BlobContainerof None.

Requester>Gridwich maakt gebruik van RequestContainerAccessChangeDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string",
        "containerName": "string",
        "accessType": "string"
    },
    "eventType": "request.blob.container.access.change"
}

Gridwich>Requester maakt gebruik van ResponseContainerAccessChangeSuccessDTO.

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "storageAccountName": "string",
        "containerName": "string",
        "accessType": "string"
    },
    "eventType": "response.blob.container.access.change.success"
}

Aanvrager vraagt Gridwich om naar een nieuwe opslagsleutel te draaien

De Rollkey gebeurtenisfamilie wijkt af van andere in Gridwich, terwijl de aanvraag een operationContext waarde accepteert, bevat geen van de reactie-gebeurtenissen deze.

Fout gebeurtenissen zijn niet van het normale type response.failure gebeurtenistype , maar hebben in plaats daarvan een typewaarde van response.rollkey.storage.failure.

De response.rollkey.storage.failure fout gebeurtenissen:

  • Neem geen gegevenseigenschappen voor de logboekregistratie log van normale fouten op.
  • Bevat een extra gegevenseigenschap met de naam error die de tekst van het foutbericht bevat. Andere Gridwich-fouten bevatten die tekst op de logEventMessage gegevenseigenschap.

Deze punten weerspiegelen de huidige status van de logische Azure-app die de rollkey-bewerking uitvoert. De definitie van de logische app bevindt zich in het bestand infrastructure/terraform/keyroller/main.tf Terraform.

De keyName naam komt overeen met de sleutelnaam die Azure Storage definieert in de bewerking Sleutels ophalen.

Requester>Gridwich

{
    "id": "GUID-string",
    "topic": "Topic-string",
    "subject": "Subject-string",
    "dataVersion": "DataVersion-string",
    "data": {
        "operationContext": <OperationContextObject>,
        "account": "storageAccountName",
        "keyName": "key1"
    },
    "eventType": "request.rollkey.storage"
}

Gridwich>Requester

  • Geslaagd:

    {
        "id": "GUID-string",
        "topic": "Topic-string",
        "subject": "Subject-string",
        "dataVersion": "DataVersion-string",
        "data": {
            "account": "storageAccountName",
            "keyName": "key1"
        },
        "eventType": "response.rollkey.storage.success"
    }
    
  • Fout:

    {
        "id": "GUID-string",
        "topic": "Topic-string",
        "subject": "Subject-string",
        "dataVersion": "1.0",
        "data": {
           "account": "storageAccountName1",
            "keyName": "key1",
            "error": "error message text"
        },
        "eventType": "response.rollkey.storage.failure"
    }
    

    Mislukte resultaten voor deze bewerking zijn niet zo voltooid als normale Gridwich-fouten.

Volgende stappen

Productdocumentatie:

Microsoft Learn-modules: