Notificação de alteração de objetos

Use a notificação de alteração de objetos para informar a um aplicativo que um objeto foi atualizado ou adicionado a um bucket.

É melhor usar a notificação de alteração de objeto?

Geralmente, não convém usar a notificação de alteração de objeto. A ferramenta recomendada para gerar notificações que rastreiam alterações em objetos em buckets do Cloud Storage é notificações de Pub/Sub para Cloud Storage, uma vez que é a mais rápida, flexível, fácil de configurar e econômica. Para ver um guia passo a passo sobre como configurar notificações do Pub/Sub para o Cloud Storage, consulte Como configurar notificações do Pub/Sub para Cloud Storage.

Como funciona a notificação de alteração de objetos

Um aplicativo cliente pode enviar uma solicitação para monitorar as alterações nos objetos de um determinado bucket.

Para concluir uma solicitação de monitoramento, é necessário criar um novo canal de notificação. Um canal de notificação é o meio usado para enviar uma mensagem de notificação a um aplicativo que está monitorando um bucket. Atualmente, há apenas um tipo de canal de notificação compatível, o webhook.

Depois que um canal de notificação é inicializado, o Cloud Storage notifica o aplicativo sempre que um objeto é adicionado, atualizado ou removido do bucket. Por exemplo, quando você adiciona uma nova imagem a um bucket, um aplicativo pode ser notificado para criar uma miniatura.

Detalhes da notificação de alteração de objetos

Terminologia

A tabela a seguir contém uma descrição de vários termos usados na documentação da notificação de alteração de objetos:

Termo Descrição
URL do aplicativo O URL do seu aplicativo. É o endereço de destino das notificações que serão enviadas. Ele precisa ser um URL HTTPS. URLs HTTP não são permitidos.
Identificador do canal O identificador do canal de notificação. Ele precisa ser exclusivo dentro do bucket, ou seja, se houver vários canais de notificação em um único bucket, cada um precisa ter um identificador diferente. Esse identificador será enviado ao seu aplicativo com cada mensagem de notificação.
Identificador do recurso Um identificador opaco do recurso que está sendo monitorado. O identificador do recurso é necessário para interromper um canal de notificação. É possível recuperar esse identificador na resposta de uma solicitação de monitoramento ou no cabeçalho X-Goog-Resource-Id das mensagens de evento de notificação.
Token do cliente (Opcional) Os tokens do cliente podem ser usados para validar os eventos de notificação. Para fazer isso, defina um token do cliente personalizado na solicitação de monitoramento. As mensagens de notificação incluirão esse token para que você verifique se são autênticas.

Como monitorar um bucket

Para começar a monitorar eventos de notificação de alteração em um bucket, faça uma solicitação watchAll. Isso cria um canal de notificação que envia eventos de notificação para o address especificado de um determinado bucket. O canal de notificação inclui um token de cliente personalizado e um identificador de canal, se especificados.

Um exemplo de solicitação POST para monitorar um bucket:

POST /storage/v1/b/BucketName/o/watch?alt=json HTTP/1.1
Host: storage.googleapis.com
Content-Length: 200
User-Agent: google-api-python-client/1.0
Content-Type: application/json
Authorization: Bearer oauth2_token

{
  "token": "ClientToken",
  "type": "web_hook",
  "id": "ChannelId",
  "address": "ApplicationUrl"
}

Autorização de notificação

Durante o monitoramento do bucket, o canal de notificação que está sendo criado será associado ao projeto no Console do Google Cloud correspondente ao aplicativo que iniciou a solicitação de API. Isso significa que, por exemplo, se um usuário conceder acesso a um aplicativo instalado ou da Web por meio de um fluxo OAuth2, o canal de notificação criado pelo aplicativo será associado ao projeto do aplicativo, e não ao projeto que contém o bucket que será monitorado.

Como uma conta de serviço está associada a um projeto, se você usar uma conta de serviço para monitorar um bucket, ela criará um canal de notificação no projeto da conta de serviço.

Como remover um canal de notificação

Para interromper um canal de notificação, faça uma solicitação stop. Isso interrompe todos os eventos de notificação para o par de identificador de recurso especificado (resourceId) e identificador de canal (id). Outros canais ativos para o mesmo recurso não são afetados. Os identificadores do recurso e do canal estão na resposta da solicitação de monitoramento ou no corpo das mensagens de evento de notificação.

Um exemplo de solicitação POST para interromper um canal:

POST /storage/v1/channels/stop HTTP/1.1
Host: storage.googleapis.com
Content-Length: 200
User-Agent: google-api-python-client/1.0
Content-Type: application/json
Authorization: Bearer oauth2_token

{
  "resourceId": "ResourceId",
  "id": "ChannelId"
}

Tipos de mensagem de evento de notificação

Sincronização

Após a emissão de uma solicitação de monitoramento, um canal de notificação novo é criado e um evento de notificação é enviado. Depois de receber o evento de sincronização, todas as alterações posteriores no bucket serão enviadas ao URL do aplicativo configurado para o canal.

A notificação será enviada ao URL configurado para o aplicativo como uma solicitação POST. A solicitação não tem corpo. Os metadados da notificação de sincronização estão contidos nos cabeçalhos da solicitação. Veja abaixo um exemplo de solicitação de notificação de sincronização:

POST /ApplicationUrlPath
Accept: */*
Content-Type: application/json; charset="utf-8"
Content_Length: 0
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: sync
X-Goog-Resource-Uri: https://storage.googleapis.com/storage/v1/b/BucketName/o?alt=json

Adição, atualização ou exclusão de objetos

Um evento de notificação é enviado quando um objeto novo é adicionado a um bucket, quando o conteúdo ou os metadados de um objeto atual são modificados ou quando um objeto é excluído de um bucket.

A notificação será enviada ao URL configurado para o aplicativo como uma solicitação POST. O corpo da solicitação contém uma mensagem em código JSON, conforme mostrado na solicitação de notificação a seguir:

POST /ApplicationUrlPath
Accept: */*
Content-Length: 1097
Content-Type: application/json; charset="utf-8"
Host: ApplicationUrlHost
X-Goog-Channel-Id: ChannelId
X-Goog-Channel-Token: ClientToken
X-Goog-Resource-Id: ResourceId
X-Goog-Resource-State: ResourceState
X-Goog-Resource-Uri: https://storage.googleapis.com/storage/v1/b/BucketName/o?alt=json

{
 "kind": "storage#object",
 "id": "BucketName/ObjectName",
 "selfLink": "https://www.googleapis.com/storage/v1/b/BucketName/o/ObjectName",
 "name": "ObjectName",
 "bucket": "BucketName",
 "generation": "1367014943964000",
 "metageneration": "1",
 "contentType": "application/octet-stream",
 "updated": "2013-04-26T22:22:23.832Z",
 "size": "10",
 "md5Hash": "xHZY0QLVuYng2gnOQD90Yw==",
 "mediaLink": "https://content-storage.googleapis.com/storage/v1/b/BucketName/o/ObjectName?generation=1367014943964000&alt=media",
 "owner": {
  "entity": "user-jane@gmail.com"
 },
 "crc32c": "C7+82w==",
 "etag": "COD2jMGv6bYCEAE="
}
onde ResourceState é:
  • exists: para adições e atualizações de objetos;
  • not_exists: para exclusões de objetos.

O conteúdo da mensagem JSON incluirá a representação atual do objeto, conforme descrito na descrição do recurso Object.

Entrega confiável

A notificação de alteração de objeto tentará enviar notificações para seu aplicativo de maneira confiável. No entanto, as notificações podem sofrer atrasos indefinidamente e a pontualidade não é garantida. Como talvez seu aplicativo nem sempre esteja disponível, as regras determinam como ocorre a entrega de notificações:

  • Se houver falha na tentativa de entrega de uma notificação, serão feitas novas tentativas. O intervalo entre as novas tentativas de entrega é determinado por um algoritmo de espera exponencial, que começa com uma nova tentativa 30 segundos após a falha inicial. As demais tentativas de entrega subsequentes são feitas em intervalos crescentes, até o máximo de 90 minutos. Observe que os intervalos entre novas tentativas são um pouco aleatórios. Portanto, eles não ocorrem em valores exponenciais exatos. Depois que for atingido o intervalo máximo de 90 minutos, as tentativas subsequentes serão feitas a cada 90 minutos por sete dias. Se não for possível entregar a notificação nesse período, ela será limpa.
  • Caso não seja possível se comunicar com seu aplicativo após 20 segundos ou se ele responder com um dos códigos de resposta HTTP a seguir, a tentativa de entrega de notificação será tratada como uma falha e uma nova tentativa será feita:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Se seu aplicativo responder com um dos códigos de resposta HTTP a seguir, a notificação será tratada como entregue:
    • 102 Processing
    • 200 OK
    • 201 Created
    • 202 Accepted
    • 204 No Content
  • Quaisquer outros códigos de resposta HTTP retornados pelo aplicativo são tratados como falhas permanentes. Nesses casos, não são feitas novas tentativas.

Exemplo de aplicativo cliente

Nesta seção, explicamos como criar um aplicativo cliente do App Engine que processa eventos de notificação de alteração.

O aplicativo do exemplo contém uma classe chamada MainPage. Quando o usuário atualiza ou adiciona um objeto ao bucket, a classe MainPage processa o evento de notificação. Para simplificar, o método post que faz o processamento real registra uma mensagem com o horário em que a notificação foi recebida. É possível substituir esse código pela lógica de processamento que você de fato usa. Caso você ainda não se sinta à vontade para desenvolver aplicativos do App Engine, tente implantar uma amostra de aplicativo ou seguir um tutorial antes de continuar.

  1. Configurar o aplicativo
    Crie o arquivo de configuração app.yaml para especificar o aplicativo cliente que processa os eventos de notificação de alteração do intervalo.
    application: APPLICATION
    version: 1
    runtime: python38
    api_version: 1
    threadsafe: true
    
    handlers:
    - url: /.*
      script: change_notification_client.app
    
  2. Como criar o aplicativo.
    Veja no exemplo a seguir como implementar um aplicativo cliente para o processamento de eventos de notificação de alteração de um intervalo. Dê a ele o nome de change_notification_client.py e implante-o:
    """Notification handling for Google Cloud Storage."""
    
    import json
    import logging
    
    import webapp2
    
    class MainPage(webapp2.RequestHandler):
      """Process notification events."""
      def get(self):
        logging.info("Get request to notification page.")
        self.response.write("Welcome to the notification app.")
    
      def post(self):  # pylint: disable-msg=C6409
        """Process the notification event.
    
        This method is invoked when the notification channel is first created with
        a sync event, and then subsequently every time an object is added to the
        bucket, updated (both content and metadata) or removed. It records the
        notification message in the log.
        """
    
        logging.debug(
            '%s\n\n%s',
            '\n'.join(['%s: %s' % x for x in self.request.headers.iteritems()]),
            self.request.body)
    
        # The following code is for demonstration. Replace
        # it with your own notification processing code.
    
        if 'X-Goog-Resource-State' in self.request.headers:
          resource_state = self.request.headers['X-Goog-Resource-State']
          if resource_state == 'sync':
            logging.info('Sync message received.')
          else:
            an_object = json.loads(self.request.body)
            bucket = an_object['bucket']
            object_name = an_object['name']
            logging.info('%s/%s %s', bucket, object_name, resource_state)
        else:
          logging.info("Other post.")
    
    logging.getLogger().setLevel(logging.DEBUG)
    app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
    
  3. Como atribuir a permissão de acesso do aplicativo ao bucket.
    Se o bucket pertencer a uma conta de serviço diferente do seu aplicativo do App Engine, conceda ao aplicativo o acesso de PROPRIETÁRIO ao bucket.
  4. Como começar a monitorar alterações de objetos do bucket
    Crie um canal de notificação para o aplicativo monitorando o bucket usando uma solicitação watchAll com o address do URL do app. do Google Cloud, por exemplo, https://ApplicationId.appspot.com/.
  5. Como testar o aplicativo
    Para ver se o aplicativo funciona conforme esperado, execute estas etapas:
    1. Para garantir que o aplicativo foi implantado e funciona corretamente, execute o comando curl a seguir:
      curl -X Post https://APPLICATION_ID.appspot.com
      
      Caso você tenha usado seu próprio nome de domínio para implantar o aplicativo, use-o em vez de appspot.com no comando anterior.
    2. Vá para a página de geração de registros do seu projeto. Atualize a lista das mensagens registradas, se necessário. Verifique se a mensagem de registro emitida pelo aplicativo foi registrada.
    3. Adicione um objeto ao bucket. O Cloud Storage notifica o aplicativo, que em seguida registra uma mensagem.
    4. Vá para a página de geração de registros do seu projeto. Atualize a lista de mensagens registradas e encontre aquela referente à cópia do objeto.
  6. Como remover o canal de notificação
    Remova o canal de notificação especificando os identificadores do canal e do recurso que foram retornados quando você emitiu o comando de notificação para monitorar bucket.