Skip to content
This repository has been archived by the owner on Mar 9, 2018. It is now read-only.

support for mongoid orm #146

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ platform :ruby do
gem 'mysql'
gem 'yajl-ruby'
gem 'sqlite3'
gem 'mongoid'
gem 'mongoid-autoinc'
#gem 'perftools.rb'
end

Expand Down
20 changes: 12 additions & 8 deletions lib/generators/rapns_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ class RapnsGenerator < Rails::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path('../templates', __FILE__)

class_option :mongoid, type: :boolean, default: false

def self.next_migration_number(path)
@time ||= Time.now.utc
@calls ||= -1
@calls += 1
(@time + @calls.seconds).strftime("%Y%m%d%H%M%S")
end

def copy_migration
add_rapns_migration('create_rapns_notifications')
add_rapns_migration('create_rapns_feedback')
add_rapns_migration('add_alert_is_json_to_rapns_notifications')
add_rapns_migration('add_app_to_rapns')
add_rapns_migration('create_rapns_apps')
add_rapns_migration('add_gcm')
if !options.mongoid?
add_rapns_migration('create_rapns_notifications')
add_rapns_migration('create_rapns_feedback')
add_rapns_migration('add_alert_is_json_to_rapns_notifications')
add_rapns_migration('add_app_to_rapns')
add_rapns_migration('create_rapns_apps')
add_rapns_migration('add_gcm')
end
end

def copy_config
def copy_config
copy_file 'rapns.rb', 'config/initializers/rapns.rb'
end

Expand Down
3 changes: 3 additions & 0 deletions lib/generators/templates/rapns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Rapns.configure do |config|

# Setup orm backend (default to active_record)
# require 'rapns/orm/{active_record|mongoid}'

# Run in the foreground?
# config.foreground = false

Expand Down
61 changes: 37 additions & 24 deletions lib/rapns.rb
Original file line number Diff line number Diff line change
@@ -1,43 +1,56 @@
require 'active_record'
require 'multi_json'

require 'rapns/version'
require 'rapns/deprecation'
require 'rapns/deprecatable'
require 'rapns/logger'
require 'rapns/multi_json_helper'
require 'rapns/configuration'

module Rapns

def self.init_orm
if Rapns.config.store == :active_record
require 'rapns/orm/active_record'
elsif Rapns.config.store == :mongoid
require 'rapns/orm/mongoid'
else
raise "Unsupported store: #{Rapns.config.store.to_s}"
end

require 'rapns/notification'
require 'rapns/app'
require 'rapns/apns/binary_notification_validator'
require 'rapns/apns/device_token_format_validator'
require 'rapns/apns/notification'
require 'rapns/apns/feedback'
require 'rapns/apns/app'

require 'rapns/gcm/expiry_collapse_key_mutual_inclusion_validator'
require 'rapns/gcm/payload_data_size_validator'
require 'rapns/gcm/registration_ids_count_validator'
require 'rapns/gcm/notification'
require 'rapns/gcm/app'

end

def self.attr_accessible_available?
require 'rails'
::Rails::VERSION::STRING < '4'
end

def self.jruby?
defined? JRUBY_VERSION
end
end

require 'rapns/version'
require 'rapns/deprecation'
require 'rapns/deprecatable'
require 'rapns/logger'
require 'rapns/multi_json_helper'
require 'rapns/notification'
require 'rapns/app'
require 'rapns/configuration'
require 'rapns/reflection'
require 'rapns/embed'
require 'rapns/push'
require 'rapns/apns_feedback'
require 'rapns/upgraded'

require 'rapns/apns/binary_notification_validator'
require 'rapns/apns/device_token_format_validator'
require 'rapns/apns/notification'
require 'rapns/apns/feedback'
require 'rapns/apns/app'

require 'rapns/gcm/expiry_collapse_key_mutual_inclusion_validator'
require 'rapns/gcm/payload_data_size_validator'
require 'rapns/gcm/registration_ids_count_validator'
require 'rapns/gcm/notification'
require 'rapns/gcm/app'

module Rapns
def self.jruby?
defined? JRUBY_VERSION
end

def self.require_for_daemon
require 'rapns/daemon'
Expand Down
16 changes: 13 additions & 3 deletions lib/rapns/apns/feedback.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
module Rapns
module Apns
class Feedback < ActiveRecord::Base
self.table_name = 'rapns_feedback'

class Feedback < Rapns::RecordBase
if Rapns.config.store == :active_record
self.table_name = 'rapns_feedback'
else

field :device_token, type: String
field :failed_at, type: DateTime

belongs_to :app, class_name: 'Rapns::App'

index({device_token: 1})
end

if Rapns.attr_accessible_available?
attr_accessible :device_token, :failed_at, :app
end
Expand Down
8 changes: 6 additions & 2 deletions lib/rapns/apns/notification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ def as_json
end

def to_binary(options = {})
id_for_pack = options[:for_validation] ? 0 : id
if Rapns.config.store == :active_record
id_for_pack = options[:for_validation] ? 0 : id
else
id_for_pack = options[:for_validation] ? 0 : validation_id
end
[1, id_for_pack, expiry, 0, 32, device_token, payload_size, payload].pack("cNNccH*na*")
end
end

def data=(attrs)
return unless attrs
Expand Down
18 changes: 15 additions & 3 deletions lib/rapns/app.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
module Rapns
class App < ActiveRecord::Base
self.table_name = 'rapns_apps'

class App < Rapns::RecordBase
if Rapns.config.store == :active_record
self.table_name = 'rapns_apps'
else

field :name, type: String
field :environment, type: String
field :certificate, type: String
field :password, type: String
field :connections, type: Integer, default: 1
field :auth_key, type: String

has_many :feedbacks, :class_name => 'Rapns::Apns::Feedback'
end

if Rapns.attr_accessible_available?
attr_accessible :name, :environment, :certificate, :password, :connections, :auth_key
end
Expand Down
1 change: 1 addition & 0 deletions lib/rapns/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def self.config

def self.configure
yield config if block_given?
Rapns.init_orm
end

CONFIG_ATTRS = [:foreground, :push_poll, :feedback_poll, :embedded,
Expand Down
12 changes: 10 additions & 2 deletions lib/rapns/daemon/apns/delivery.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,17 @@ def check_for_error

if tuple = @connection.read(ERROR_TUPLE_BYTES)
cmd, code, notification_id = tuple.unpack("ccN")

description = APN_ERRORS[code.to_i] || "Unknown error. Possible rapns bug?"
error = Rapns::DeliveryError.new(code, notification_id, description)

if Rapns.config.store == :active_record
error = Rapns::DeliveryError.new(code, notification_id, description)
else
notification = Rapns::Apns::Notification.where(validation_id: notification_id).first
error = Rapns::DeliveryError.new(code, notification ? notification.id : 0, description)
end

error
else
error = Rapns::Apns::DisconnectionError.new
end
Expand Down
60 changes: 60 additions & 0 deletions lib/rapns/daemon/store/mongoid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
require 'mongoid'

module Rapns
module Daemon
module Store
class Mongoid

def deliverable_notifications(apps)
batch_size = Rapns.config.batch_size
relation = Rapns::Notification.ready_for_delivery.for_apps(apps)
relation = relation.limit(batch_size) unless Rapns.config.push
relation.to_a
end

def retry_after(notification, deliver_after)
notification.retries += 1
notification.deliver_after = deliver_after
notification.save!(:validate => false)
end

def mark_delivered(notification)
notification.delivered = true
notification.delivered_at = Time.now
notification.save!(:validate => false)
end

def mark_failed(notification, code, description)
notification.delivered = false
notification.delivered_at = nil
notification.failed = true
notification.failed_at = Time.now
notification.error_code = code
notification.error_description = description
notification.save!(:validate => false)
end

def create_apns_feedback(failed_at, device_token, app)
Rapns::Apns::Feedback.create!(:failed_at => failed_at,
:device_token => device_token, :app => app)
end

def create_gcm_notification(attrs, data, registration_ids, deliver_after, app)
notification = Rapns::Gcm::Notification.new
notification.assign_attributes(attrs)
notification.data = data
notification.registration_ids = registration_ids
notification.deliver_after = deliver_after
notification.app = app
notification.save!
notification
end

def after_daemonize

end

end
end
end
end
70 changes: 55 additions & 15 deletions lib/rapns/notification.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,60 @@
module Rapns
class Notification < ActiveRecord::Base
class Notification < Rapns::RecordBase
include Rapns::MultiJsonHelper

self.table_name = 'rapns_notifications'

# TODO: Dump using multi json.
serialize :registration_ids
if Rapns.config.store == :active_record
self.table_name = 'rapns_notifications'

scope :ready_for_delivery, lambda {
where('delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)',
false, false, Time.now)
}

scope :for_apps, lambda { |apps|
where('app_id IN (?)', apps.map(&:id))
}

# TODO: Dump using multi json.
serialize :registration_ids

else
include Mongoid::Autoinc

field :badge, type: Integer
field :device_token, type: String
field :sound, type: String, default: "default"
field :alert, type: String
field :data, type: String
field :expiry, type: Integer, default: 86400
field :delivered, type: Boolean, default: false
field :delivered_at, type: DateTime
field :failed, type: Boolean, default: false
field :failed_at, type: DateTime
field :deliver_after, type: DateTime
field :alert_is_json, type: Boolean, default: false
field :collapse_key, type: String
field :delay_while_idle, type: Boolean, default: false
field :registration_ids, type: Array
field :app_id, type: Integer
field :retries, type: Integer, default: 0
field :error_code, type: Integer
field :error_description, type: String
field :validation_id, type: Integer

increments :validation_id

index({app_id: 1, delivered: -1, failed: -1, deliver_after: -1})
index({delivered: -1, failed: -1, deliver_after: -1})

scope :ready_for_delivery, lambda {
where({"$and" => [delivered: false, failed: false, "$or" => [{"$deliver_after.ne" => nil}, deliver_after: {"$lt" => Time.now}]]})
}

scope :for_apps, lambda { |apps|
where(app_id: {"$in" => apps.map(&:id)})
}

end

belongs_to :app, :class_name => 'Rapns::App'

Expand All @@ -17,16 +66,7 @@ class Notification < ActiveRecord::Base

validates :expiry, :numericality => true, :allow_nil => true
validates :app, :presence => true

scope :ready_for_delivery, lambda {
where('delivered = ? AND failed = ? AND (deliver_after IS NULL OR deliver_after < ?)',
false, false, Time.now)
}

scope :for_apps, lambda { |apps|
where('app_id IN (?)', apps.map(&:id))
}


def initialize(*args)
attributes = args.first
if attributes.is_a?(Hash) && attributes.keys.include?(:attributes_for_device)
Expand Down
7 changes: 7 additions & 0 deletions lib/rapns/orm/active_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'active_record'

module Rapns
class RecordBase < ActiveRecord::Base
self.abstract_class = true
end
end
13 changes: 13 additions & 0 deletions lib/rapns/orm/mongoid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'mongoid'
require 'autoinc'

module Rapns
class RecordBase
include Mongoid::Document
include Mongoid::Timestamps

store_in collection: 'rapns'
end

self.config.store = :mongoid
end
Loading