Статьи

Работа с просроченными каналами в мобильных службах Windows Azure

 

Что это? Еще одна публикация Windows Azure Mobile Services (WAMS) ?! 

В следующей версии моего приложения я веду запись канала пользователя для отправки уведомлений. Пример встроенного списка задач делает это или что-то очень похожее. Моя таблица в WAMS выглядит так:

образ

Не показаны пара полей, но особый интерес представляет идентификатор устройства. Я понял, что у одного пользователя может быть несколько устройств, поэтому канал привязывается к идентификатору устройства. Я до сих пор не нашел идеального способа сделать это — сейчас я использую случайный GUID при первом запуске. 

В моем сценарии WAMS, если отправленная точка находится «в пределах досягаемости» другого пользователя, мы отправим уведомление вниз, чтобы обновить плитку. Я вхожу в эту часть в своем блоге:  лучшие практики по отправке живых плиток . Но что делать, если срок действия канала истек? Это часто встречается в тестировании, потому что приложение удалялось / переустанавливалось много раз. 

Я наткнулся на эту страницу, заголовки запросов и ответов службы push-уведомлений в MSDN. На этой странице много интересной информации. В то время как у меня должно быть более надежное решение для обработки всех этих условий, особенно меня интересует ответ Channel Expired, выделенный ниже:

Код ответа HTTP Описание Рекомендованное действие
200 ОК Уведомление было принято WNS. Не требуется
ошибка 400, неверный запрос Один или несколько заголовков были указаны неправильно или конфликтуют с другим заголовком. Запишите детали вашего запроса. Проверьте ваш запрос и сравните с этой документацией.
401 Несанкционированный Облачный сервис не предоставил действительный билет аутентификации. Билет OAuth может быть недействительным. Запросите действительный токен доступа, аутентифицируя облачную службу с помощью запроса токена доступа.
403 Запрещено Облачной службе не разрешено отправлять уведомления на этот URI, даже если они аутентифицированы. Маркер доступа, указанный в запросе, не соответствует учетным данным приложения, которое запросило URI канала. Убедитесь, что имя вашего пакета в манифесте вашего приложения совпадает с учетными данными облачной службы, предоставленными вашему приложению на информационной панели.
404 Не Найдено URI канала недействителен или не распознается WNS. Запишите детали вашего запроса. Не отправлять дальнейшие уведомления на этот канал; уведомления на этот адрес не пройдут.
405 метод не разрешен Неверный метод (GET, DELETE, CREATE); допускается только POST. Запишите детали вашего запроса. Переключитесь на использование HTTP POST.
406 Недопустимо Облачный сервис превысил свой предел газа. Запишите детали вашего запроса. Уменьшите скорость, с которой вы отправляете уведомления.
410 ушел Канал истек. Запишите детали вашего запроса. Не отправлять дальнейшие уведомления на этот канал. Ваше приложение запрашивает новый URI канала .
413 Запросить объект слишком большой Полезная нагрузка уведомления превышает ограничение размера 5000 байт. Запишите детали вашего запроса. Проверьте полезную нагрузку, чтобы убедиться, что она соответствует ограничениям по размеру.
500 — внутренняя ошибка сервера Внутренний сбой вызвал сбой доставки уведомлений. Запишите детали вашего запроса. Сообщите об этой проблеме через форумы разработчиков .
503 Служба Недоступна Сервер в данный момент недоступен. Запишите детали вашего запроса. Сообщите об этой проблеме через форумы разработчиков .

Очевидно, что получение нового URI канала является идеальным, но приложение должно делать это на клиенте (и будет) в следующий раз, когда пользователь запустит приложение. А пока я хочу удалить этот канал, потому что он бесполезен. В моем сценарии, который отправляет уведомления, мы изучим результат обратного вызова и либо удалим канал, если срок его действия истек, либо, в случае успеха, отправим обновление значка, потому что это тоже необходимо. (Задача на будущее: попробуйте объединить Live Tile и значки в одном обновлении.)

push.wns.send(channelUri, payload, 'wns/tile', 
 {
        client_id: 'ms-app://<my app id>',
        client_secret: 'my client secret',
        headers: { 'X-WNS-Tag' : 'SomeTag' }   
 }, 
      function (error, result) {
      if (error)
      {
          //if the channel has expired, delete from channel table
          if (error.statusCode == 410){
              removeExpiredChannel(channelUri)               
          }
      }
      else
      {
            //notification sent
            updateBadge(channelUri);
      }
    }
);

Удаление просроченных каналов может быть сделано с помощью чего-то вроде:

function removeExpiredChannel(channelUri) 
{                  
       var sql = "delete from myapp.Channel where ChannelUri = ?";
       var params = [channelUri];       
       mssql.query(sql, params,
       {
            success: function(results) {
                console.log('Removed Expired Channel: ' + channelUri)
        }
    });
} 

В моем списке задач стоит добавить более надежную поддержку различных кодов ответов — например, в дополнение к ответу 410, 404 также хотел бы удалить запись канала в таблице.