class Rpush::Daemon::Wns::Delivery

msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx

Constants

ACCESS_TOKEN_REQUEST_DATA

Data used to request authorization tokens.

FAILURE_MESSAGES
MAX_RETRIES
WPN_TOKEN_URI

Oauth2.0 token endpoint. This endpoint is used to request authorization tokens.

Public Class Methods

new(app, http, notification, batch) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 27
def initialize(app, http, notification, batch)
  @app = app
  @http = http
  @notification = notification
  @batch = batch
end

Public Instance Methods

perform() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 34
def perform
  handle_response(do_post)
rescue SocketError => error
  mark_retryable(@notification, Time.now + 10.seconds, error)
  raise
rescue StandardError => error
  mark_failed(error)
  raise
ensure
  @batch.notification_processed
end

Private Instance Methods

access_token() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 150
def access_token
  if @notification.app.access_token.nil? || @notification.app.access_token_expired?
    post = Net::HTTP::Post.new(WPN_TOKEN_URI.path, 'Content-Type' => 'application/x-www-form-urlencoded')
    post.set_form_data(ACCESS_TOKEN_REQUEST_DATA.merge('client_id' => @notification.app.client_id, 'client_secret' => @notification.app.client_secret))

    handle_access_token(@http.request(WPN_TOKEN_URI, post))
  end

  @notification.app.access_token
end
do_post() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 134
def do_post
  post = PostRequest.create(@notification, access_token)
  @http.request(URI.parse(@notification.uri), post)
end
handle_access_token(response) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 161
def handle_access_token(response)
  if response.code.to_i == 200
    update_access_token(JSON.parse(response.body))
    Rpush::Daemon.store.update_app(@notification.app)
    log_info("WNS access token updated: token = #{@notification.app.access_token}, expires = #{@notification.app.access_token_expiration}")
  else
    log_warn("Could not retrieve access token from WNS: #{response.body}")
  end
end
handle_failure(code, msg = nil) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 70
def handle_failure(code, msg = nil)
  unless msg
    msg = FAILURE_MESSAGES.key?(code) ? FAILURE_MESSAGES[code] : Rpush::Daemon::HTTP_STATUS_CODES[code]
  end
  fail Rpush::DeliveryError.new(code, @notification.id, msg)
end
handle_response(response) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 48
def handle_response(response)
  code = response.code.to_i
  case code
  when 200
    ok(response)
  when 401
    unauthorized
  when 404
    invalid_channel(code)
  when 406
    not_acceptable
  when 410
    invalid_channel(code)
  when 412
    precondition_failed
  when 503
    service_unavailable
  else
    handle_failure(code)
  end
end
invalid_channel(code, msg = nil) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 103
def invalid_channel(code, msg = nil)
  unless msg
    msg = FAILURE_MESSAGES.key?(code) ? FAILURE_MESSAGES[code] : Rpush::Daemon::HTTP_STATUS_CODES[code]
  end
  reflect(:wns_invalid_channel, @notification, @notification.uri, "#{code}. #{msg}")
  handle_failure(code, msg)
end
not_acceptable() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 111
def not_acceptable
  retry_notification("Per-day throttling limit reached.")
end
ok(response) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 77
def ok(response)
  status = status_from_response(response)
  case status[:notification]
  when ["received"]
    mark_delivered
    log_info("#{@notification.id} sent successfully")
  when ["channelthrottled"]
    mark_retryable(@notification, Time.now + (60 * 10))
    log_warn("#{@notification.id} cannot be sent. The Queue is full.")
  when ["dropped"]
    log_error("#{@notification.id} was dropped. Headers: #{status}")
    handle_failure(200, "Notification was received but suppressed by the service (#{status[:error_description]}).")
  end
end
precondition_failed() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 115
def precondition_failed
  retry_notification("Device unreachable.")
end
retry_message() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 124
def retry_message
  "Notification #{@notification.id} will be retried after #{@notification.deliver_after.strftime('%Y-%m-%d %H:%M:%S')} (retry #{@notification.retries})."
end
retry_notification(reason) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 128
def retry_notification(reason)
  deliver_after = Time.now + (60 * 60)
  mark_retryable(@notification, deliver_after)
  log_warn("#{reason} " + retry_message)
end
service_unavailable() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 119
def service_unavailable
  mark_retryable_exponential(@notification)
  log_warn("Service Unavailable. " + retry_message)
end
status_from_response(response) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 139
def status_from_response(response)
  headers = response.to_hash.each_with_object({}) { |e, a| a[e[0].downcase] = e[1] }
  {
    notification:         headers["x-wns-status"],
    device_connection:    headers["x-wns-deviceconnectionstatus"],
    msg_id:               headers["x-wns-msg-id"],
    error_description:    headers["x-wns-error-description"],
    debug_trace:          headers["x-wns-debug-trace"]
  }
end
unauthorized() click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 92
def unauthorized
  @notification.app.access_token = nil
  Rpush::Daemon.store.update_app(@notification.app)
  if @notification.retries < MAX_RETRIES
    retry_notification("Token invalid.")
  else
    msg = "Notification failed to be delivered in #{MAX_RETRIES} retries."
    mark_failed(Rpush::DeliveryError.new(nil, @notification.id, msg))
  end
end
update_access_token(data) click to toggle source
# File lib/rpush/daemon/wns/delivery.rb, line 171
def update_access_token(data)
  @notification.app.access_token = data['access_token']
  @notification.app.access_token_expiration = Time.now + data['expires_in'].to_i
end