Share via


Exporter et importer en bloc des inscriptions Azure Notification Hubs

Certains scénarios nécessitent de créer ou modifier un grand nombre d’inscriptions dans un hub de notifications. Les mises à jour des étiquettes après des calculs par lots ou la migration d’une implémentation push existante pour utiliser Azure Notification Hubs en sont deux exemples.

Cet article explique comment effectuer un grand nombre d’opérations sur un hub de notifications ou exporter l’ensemble des inscriptions, en bloc.

REMARQUE : L’importation/exportation en bloc est disponible uniquement pour le niveau tarifaire « Standard »

Flux général

La prise en charge du traitement par lots vise à permettre l’exécution de travaux durables impliquant des millions d’inscriptions. Pour répondre à cette charge de travail, la prise en charge du traitement par lots utilise le stockage Azure pour stocker la sortie et les détails des tâches. Pour les opérations de mise à jour en bloc, l’utilisateur doit créer un fichier dans un conteneur d’objets blob, dans lequel sont listées les opérations de mise à jour des inscriptions. Quand il démarre le travail, l’utilisateur fournit une URL vers l’objet blob d’entrée ainsi qu’une URL vers un répertoire de sortie (également dans un conteneur d’objets blob). Une fois que le travail a démarré, l’utilisateur peut vérifier l’état en interrogeant l’emplacement de l’URL indiqué au démarrage du travail. Un travail donné peut uniquement effectuer des opérations d’un type spécifique (création, mise à jour ou suppression). Les opérations d’exportation sont effectuées de façon analogue.

Importer

Configurer

Cette section suppose la présence des entités suivantes :

Créer un fichier d’entrée et le stocker dans un objet blob

Un fichier d’entrée contient une liste d’inscriptions sérialisées en XML, à raison d’une par ligne. En utilisant le SDK Azure, l’exemple de code suivant montre comment sérialiser les inscriptions et les charger dans le conteneur d’objets blob :

private static async Task SerializeToBlobAsync(BlobContainerClient container, RegistrationDescription[] descriptions)
{
     StringBuilder builder = new StringBuilder();
     foreach (var registrationDescription in descriptions)
     {
          builder.AppendLine(registrationDescription.Serialize());
     }

     var inputBlob = container.GetBlobClient(INPUT_FILE_NAME);
     using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
     {
         await inputBlob.UploadAsync(stream);
     }
}

Important

Le code ci-dessus sérialise les inscriptions en mémoire, puis charge le flux entier dans un objet blob. Si vous avez chargé un fichier plus gros que quelques mégaoctets, consultez l’aide sur les objets blob Azure pour savoir comment effectuer ces étapes, par exemple, les objets blob de blocs.

Créer des jetons d’URL

Après avoir chargé votre fichier d’entrée, générez les URL du fichier d’entrée et du répertoire de sortie à fournir à votre hub de notifications. Vous pouvez utiliser deux conteneurs d’objets blob différents pour l’entrée et la sortie.

static Uri GetOutputDirectoryUrl(BlobContainerClient container)
{
      Console.WriteLine(container.CanGenerateSasUri);
      BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.All, DateTime.UtcNow.AddDays(1));
      return container.GenerateSasUri(builder);
}

static Uri GetInputFileUrl(BlobContainerClient container, string filePath)
{
      Console.WriteLine(container.CanGenerateSasUri);
      BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.Read, DateTime.UtcNow.AddDays(1));
      return container.GenerateSasUri(builder);
}

Envoi du travail

Quand vous avez les deux URL d’entrée et de sortie, vous êtes prêt à démarrer le traitement du travail par lots.

NotificationHubClient client = NotificationHubClient.CreateClientFromConnectionString(CONNECTION_STRING, HUB_NAME);
var job = await client.SubmitNotificationHubJobAsync(
     new NotificationHubJob {
             JobType = NotificationHubJobType.ImportCreateRegistrations,
             OutputContainerUri = outputContainerSasUri,
             ImportFileUri = inputFileSasUri
         }
     );

long i = 10;
while (i > 0 && job.Status != NotificationHubJobStatus.Completed)
{
    job = await client.GetNotificationHubJobAsync(job.JobId);
    await Task.Delay(1000);
    i--;
}

En plus des URL d’entrée et de sortie, cet exemple crée un objet NotificationHubJob qui contient un objet JobType d’un des types suivants :

  • ImportCreateRegistrations
  • ImportUpdateRegistrations
  • ImportDeleteRegistrations

Une fois l’appel terminé, le travail est poursuivi par le hub de notifications. Vous pouvez vérifier l’état du travail en appelant GetNotificationHubJobAsync.

À l’issue du travail, vous pouvez examiner les résultats dans les fichiers suivants situés dans votre répertoire de sortie :

  • /<hub>/<jobid>/Failed.txt
  • /<hub>/<jobid>/Output.txt

Ces fichiers contiennent la liste des opérations traitées par lots qui ont réussi ou échoué. Le fichier est au format .cvs : chaque ligne a le numéro de ligne du fichier d’entrée d’origine et contient la sortie de l’opération (généralement la description de l’inscription créée ou mise à jour).

Exemple de code complet

L’exemple de code suivant importe des inscriptions vers un hub de notifications.

using Microsoft.Azure.NotificationHubs;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        private static string CONNECTION_STRING = "namespace"; 
        private static string HUB_NAME = "demohub";
        private static string INPUT_FILE_NAME = "CreateFile.txt";
        private static string STORAGE_ACCOUNT_CONNECTIONSTRING = "connectionstring";
        private static string CONTAINER_NAME = "containername";

        static async Task Main(string[] args)
        {
            var descriptions = new[]
            {
                new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMkUxREQFBlVTTkMwMQ"),
                new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMjUxREQFBlVTTkMwMQ"),
                new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMhUxREQFBlVTTkMwMQ"),
                new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMdUxREQFBlVTTkMwMQ"),
            };

            // Get a reference to a container named "sample-container" and then create it
            BlobContainerClient container = new BlobContainerClient(STORAGE_ACCOUNT_CONNECTIONSTRING, CONTAINER_NAME);

            await container.CreateIfNotExistsAsync();

            await SerializeToBlobAsync(container, descriptions);

            // TODO then create Sas
            var outputContainerSasUri = GetOutputDirectoryUrl(container);
            
            BlobContainerClient inputcontainer = new BlobContainerClient(STORAGE_ACCOUNT_CONNECTIONSTRING, STORAGE_ACCOUNT_CONNECTIONSTRING + "/" +         INPUT_FILE_NAME);

            var inputFileSasUri = GetInputFileUrl(inputcontainer, INPUT_FILE_NAME);


            // Import this file
            NotificationHubClient client = NotificationHubClient.CreateClientFromConnectionString(CONNECTION_STRING, HUB_NAME);
            var job = await client.SubmitNotificationHubJobAsync(
                new NotificationHubJob {
                    JobType = NotificationHubJobType.ImportCreateRegistrations,
                    OutputContainerUri = outputContainerSasUri,
                    ImportFileUri = inputFileSasUri
                }
            );

            long i = 10;
            while (i > 0 && job.Status != NotificationHubJobStatus.Completed)
            {
                job = await client.GetNotificationHubJobAsync(job.JobId);
                await Task.Delay(1000);
                i--;
            }
        }

        private static async Task SerializeToBlobAsync(BlobContainerClient container, RegistrationDescription[] descriptions)
        {
            StringBuilder builder = new StringBuilder();
            foreach (var registrationDescription in descriptions)
            {
                builder.AppendLine(registrationDescription.Serialize());
            }

            var inputBlob = container.GetBlobClient(INPUT_FILE_NAME);
            using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
            {
                await inputBlob.UploadAsync(stream);
            }
        }

        static Uri GetOutputDirectoryUrl(BlobContainerClient container)
        {
            Console.WriteLine(container.CanGenerateSasUri);
            BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.All, DateTime.UtcNow.AddDays(1));
            return container.GenerateSasUri(builder);
        }

        static Uri GetInputFileUrl(BlobContainerClient container, string filePath)
        {
            Console.WriteLine(container.CanGenerateSasUri);
            BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.Read, DateTime.UtcNow.AddDays(1));
            return container.GenerateSasUri(builder);

        }
    }
}

Exporter

L’exportation des inscriptions est similaire à leur importation, avec toutefois les différences suivantes :

  • Vous avez uniquement besoin de l’URL de sortie.
  • Vous créez un travail NotificationHubJob de type ExportRegistrations.

Exemple d’extrait de code

Voici un exemple d’extrait de code qui exporte des inscriptions en Java :

// Submit an export job
NotificationHubJob job = new NotificationHubJob();
job.setJobType(NotificationHubJobType.ExportRegistrations);
job.setOutputContainerUri("container uri with SAS signature");
job = hub.submitNotificationHubJob(job);

// Wait until the job is done
while(true){
    Thread.sleep(1000);
    job = hub.getNotificationHubJob(job.getJobId());
    if(job.getJobStatus() == NotificationHubJobStatus.Completed)
        break;
}

Étapes suivantes

Pour plus d’informations sur les inscriptions, consultez les articles suivants :