alloy / lowdown Goto Github PK
View Code? Open in Web Editor NEWA Ruby client for the HTTP/2 version of the Apple Push Notification Service.
License: MIT License
A Ruby client for the HTTP/2 version of the Apple Push Notification Service.
License: MIT License
Hi alloy,
After I user the certificate to establish a lowdown client,
the client's default_topic shows "!xxxxxx". ( '!' + bundle id )
Then when I send push notifications to devices, apns response me 400 with reason "TopicDisallowed".
It happens to 5/32 apps.
Do you have any idea?
In development environment with spring enabled, either in console or sidekiq worker,
client = Lowdown::Client.production false, certificate: File.read('/path/to/apple_push_notification.pem')`
will get error message "fatal: No live threads left. Deadlock?"
When exiting console, will get message "Couldn't cleanly terminate all actors in 10 seconds!"
it works fine without spring.
Completely naive thoughts (needs more proper profiling!) are:
This is for when you have many clients but want to limit the number of connections, e.g. an instance on every thread where there are many threads (Sidekiq).
Hi,
I am testing the sample code (simple.rb in the examples folder) but getting an error as below. I am using Rails 4.2.5 with ruby 2.3.0p0.
I, [2016-04-12T17:51:52.625539 #23982] INFO -- : [APNS Connection#0x7fd8e3140ed8] Connecting... notification: #<Lowdown::Notification:0x007fd8e21e2f90 @token="XXXXXXXXXXXXXXXXXXXX", @id=1, @payload={:alert=>"Hello HTTP/2! ID=1"}> W, [2016-04-12T17:51:52.627668 #23982] WARN -- : [APNS Connection#0x7fd8e3140ed8] Defer performing request, because the connection has not been established yet. I, [2016-04-12T17:51:53.786826 #23982] INFO -- : [APNS Connection#0x7fd8e3140ed8] Connection established. E, [2016-04-12T17:51:54.092417 #23982] ERROR -- : Actor crashed! EOFError: end of file reached /Users/danolee/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in
sysread_nonblock'
/Users/danolee/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in read_nonblock' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:42:in
block in sysread'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:390:in synchronize' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:40:in
sysread'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:129:in readpartial' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/lowdown-0.3.1/lib/lowdown/connection.rb:223:in
block in runloop'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in loop' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in
runloop'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in public_send' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in
dispatch'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/call/async.rb:7:in dispatch' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in
block in dispatch'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in block in task' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in
block in task'
/Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in block in initialize' /Users/danolee/.rvm/gems/ruby-2.3.0@rails42/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in
block in create'
I, [2016-04-12T17:51:54.092732 #23982] INFO -- : [APNS Connection#0x7fd8e3140ed8] Closing...
[!] Error occurred: end of file reached
Sleep for 5 seconds`
The .pem file and the token are valid ones.
I like Lowdown because it supports the newer version of APN HTTP/2. Looks like a nice gem, thanks for your efforts.
My users also require Android support. Do you know of any gems that allow me to target APN v2 and also Android?
Hi Alloy!
I was trying to use lowdown with sidekiq with an open connection:
I have added method push_notification, which reuse existing client connection. Made lowdown client as a singleton.
class Lowdown::Client
def push_notification(notification, &callback)
connection.open unless connection.open?
send_notification(notification, &callback)
end
end
But I'm receiving "RuntimeError: Connection already open." from sidekiq workers.
Do you have any recommendations how to use lowdown with sidekiq?
Hi there,
I've been looking at this gem and it looks very interesting! You mention that you're currently testing it, and I see the last commit was ~2.5 weeks ago. How is the testing going? Is this close to production ready?
Using a PEM certificate with a passphrase results in:
TypeError - no implicit conversion of Hash into String:
lowdown (0.2.0) lib/lowdown/certificate.rb:34:in initialize' lowdown (0.2.0) lib/lowdown/certificate.rb:34:in
new'
lowdown (0.2.0) lib/lowdown/certificate.rb:34:in from_pem_data' lowdown (0.2.0) lib/lowdown/certificate.rb:19:in
certificate'
Appears as if there's no way to initialize a Lowdown::Client using a certificate with a passphrase. Although there seems to be passphrase support in lib/lowdown/certificate.rb. Just no way to pass in the parameter.
After resolving #18 by updating I'm stuck with 400 (Bad request): BadDeviceToken. At first I was sure the problem was on my end so I regenerated the certificate (again), regenerated the provisioning profile and obtained a new device token. After which I was still getting the same error.
I tried houston and it was able to send a push notification with the same certificate/token.
lowdown output:
lowdown --verbose --debug -m "Test" -c ~/Desktop/courier.pem "TOKEN"
W, [2016-04-21T14:39:16.713108 #1547] WARN -- : Dangerously suspending task: type=:call, meta={:dangerous_suspend=>true, :method_name=>:initialize}, status=:callwait
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:41:in `response'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:45:in `value'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/proxy/sync.rb:22:in `method_missing'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/proxy/cell.rb:12:in `_send_'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid.rb:207:in `new_link'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:137:in `__spawn_actor__'
I, [2016-04-21T14:39:16.714120 #1547] INFO -- : [APNS Connection#0x7fa2fa9459b8] Connecting...
W, [2016-04-21T14:39:16.716218 #1547] WARN -- : [APNS Connection#0x7fa2fa9459b8] Defer performing request, because the connection has not been established yet.
I, [2016-04-21T14:39:17.227672 #1547] INFO -- : [APNS Connection#0x7fa2fa9459b8] Connection established.
A, [2016-04-21T14:39:17.593979 #1547] ANY -- : [f0281baf4cab20443e9a060ccd866f1b5831d3b35f042a04b70a885a361f13b5 #1] 400 (Bad request): BadDeviceToken
I, [2016-04-21T14:39:17.595159 #1547] INFO -- : [APNS Connection#0x7fa2fa9459b8] Closing...
W, [2016-04-21T14:39:17.725619 #1547] WARN -- : Dangerously suspending task: type=:finalizer, meta={:dangerous_suspend=>true, :method_name=>:__shutdown__}, status=:receiving
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:230:in `receive'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid.rb:395:in `receive'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/future.rb:90:in `value'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `block in __shutdown__'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `each'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `__shutdown__'
W, [2016-04-21T14:39:17.725756 #1547] WARN -- : Terminating task: type=:finalizer, meta={:dangerous_suspend=>true, :method_name=>:__shutdown__}, status=:receiving
Celluloid::Task::Fibered backtrace unavailable. Please try `Celluloid.task_class = Celluloid::Task::Threaded` if you need backtraces here.
HI,
I use sidekiq to send the push notification and found that the delivery job does not terminate itself after the job had been done.
I send TTIN signal to sidekiq process and get many warning of celluloid at stack.
Can you give me some suggestions to solve this problem, does it cause by sidekiq or celluloid?
2016-04-15T09:11:07.903Z 32518 TID-8z7ms WARN: Thread TID-owhjjp2w0
2016-04-15T09:11:07.903Z 32518 TID-8z7ms WARN: /home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:58:in `select'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:58:in `run_once'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/mailbox/evented.rb:50:in `check'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:155:in `block in run'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/timers-4.1.1/lib/timers/group.rb:66:in `wait'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:152:in `run'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:131:in `block in start'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-essentials-0.20.5/lib/celluloid/internals/thread_handle.rb:14:in `block in initialize'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/actor/system.rb:78:in `block in get_thread'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/group/spawner.rb:50:in `call'
/home/deployer/ruby_servers/pushnotificationmanager/shared/bundle/ruby/2.2.0/gems/celluloid-0.17.3/lib/celluloid/group/spawner.rb:50:in `block in instantiate'
class ApplePushNotificationService
def initialize(cert_dev, cert_pro)
@cert_dev = cert_dev
@cert_pro = cert_pro
@pro_mutex = Mutex.new
@dev_mutex = Mutex.new
end
def deliver(tokens, payload, is_dev = false)
begin
failure_tokens = []
client = production if is_dev == false
client = development if is_dev == true
client.connect do |group|
tokens.each do |token|
notification = notification(token, payload)
group.send_notification(notification) do |response|
if !response.success?
failure_tokens.push token if is_dev == false
end
end
end
end
deliver(failure_tokens, payload, true) if is_dev == false && failure_tokens.present?
rescue Exception => e
Rails.logger.error "[!] Exception occurred at: #{e.inspect}\n\t#{e.backtrace.join("\n\t")}"
end
end
private
def production
client = nil
@pro_mutex.synchronize do
require 'lowdown'
@pro_client ||= Lowdown::Client.production(true, certificate: @cert_pro)
client = @pro_client
end
client
end
def development
client = nil
@dev_mutex.synchronize do
require 'lowdown'
@dev_client ||= Lowdown::Client.production(false, certificate: @cert_dev)
client = @dev_client
end
client
end
def notification(token, payload, expires_in = Time.now + 7.days)
require 'lowdown'
notification = Lowdown::Notification.new(token: token, expiration: expires_in)
notification.payload = payload
notification
end
end
Is there any option provided to fetch the current list of those devices that have repeatedly reported failed-delivery attempts?
We can access the production feedback service via feedback.push.apple.com on port 2196 and the development feedback service via feedback.sandbox.push.apple.com on port 2196.
I create a class for sending push notificatino by lowdown client, and I want to send to production and development device by a recursive call.
If I call this for single sidekiq job, it works well.
But when I create multi-job on sidekiq, it actor broken.
the error message is
ERROR -- : Actor crashed!
ArgumentError: this IO is already registered with selector
/Users/RayWay/.rvm/gems/ruby-2.2.1/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:42:in `register'
and this is my code (simplified)
def initialize(cert_dev, cert_pro)
@cert_dev = cert_dev
@cert_pro = cert_pro
@pro_mutex = Mutex.new
@dev_mutex = Mutex.new
end
def deliver
client = dev for loop 1
client = pro for loop 2
#connect and send push notification
deliver() # recursive call
end
def production
client = nil
@pro_mutex.synchronize do
require 'lowdown'
@client ||= Lowdown::Client.production(true, certificate: @cert_pro, keep_alive: true)
client = @client
end
client
end
def development
client = nil
@dev_mutex.synchronize do
require 'lowdown'
@client ||= Lowdown::Client.production(false, certificate: @cert_dev, keep_alive: true)
client = @client
end
client
end
I've been able to successfully send notifications in the past but whatever I try at the moment gives me an error. I tried both using the CLI and from pry
. All result in the same error.
Looking at the stack trace the problem seems to be in openssl, so I tried regenerating my push certificate as well. After doing the certificate dance I'm still getting the error.
I was able to send a push notification with the same certificate/token using houston.
Logs / stack trace:
lowdown --debug --verbose -e "production" -m "Test" -c certificate.pem "[token]"
W, [2016-04-21T13:01:51.650617 #98370] WARN -- : Dangerously suspending task: type=:call, meta={:dangerous_suspend=>true, :method_name=>:initialize}, status=:callwait
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:41:in `response'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:45:in `value'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/proxy/sync.rb:22:in `method_missing'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/proxy/cell.rb:12:in `_send_'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid.rb:207:in `new_link'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:137:in `__spawn_actor__'
I, [2016-04-21T13:01:51.651909 #98370] INFO -- : [APNS Connection#0x7ff9bc9ede10] Connecting...
W, [2016-04-21T13:01:51.654349 #98370] WARN -- : [APNS Connection#0x7ff9bc9ede10] Defer performing request, because the connection has not been established yet.
I, [2016-04-21T13:01:52.212565 #98370] INFO -- : [APNS Connection#0x7ff9bc9ede10] Connection established.
D, [2016-04-21T13:01:52.212630 #98370] DEBUG -- : [APNS Connection#0x7ff9bc9ede10] Maximum number of streams: 500. Flushing 1 enqueued requests.
D, [2016-04-21T13:01:52.212854 #98370] DEBUG -- : [APNS Connection#0x7ff9bc9ede10] [00000000-0000-0000-0000-000000000001] Performing request
E, [2016-04-21T13:01:52.377537 #98370] ERROR -- : Actor crashed!
EOFError: end of file reached
/Users/klaaspieter/.rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in `sysread_nonblock'
/Users/klaaspieter/.rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in `read_nonblock'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:42:in `block in sysread'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:390:in `synchronize'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:40:in `sysread'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:129:in `readpartial'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:223:in `block in runloop'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in `loop'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in `runloop'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in `public_send'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in `dispatch'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/async.rb:7:in `dispatch'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in `block in dispatch'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in `block in task'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in `block in task'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in `block in initialize'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in `block in create'
I, [2016-04-21T13:01:52.377761 #98370] INFO -- : [APNS Connection#0x7ff9bc9ede10] Closing...
D, [2016-04-21T13:01:52.506076 #98370] DEBUG -- : Terminating 6 actors...
W, [2016-04-21T13:01:52.507216 #98370] WARN -- : Dangerously suspending task: type=:finalizer, meta={:dangerous_suspend=>true, :method_name=>:__shutdown__}, status=:receiving
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:230:in `receive'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid.rb:395:in `receive'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/future.rb:90:in `value'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `block in __shutdown__'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `each'
/Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-pool-0.20.5/lib/celluloid/supervision/container/pool.rb:39:in `__shutdown__'
D, [2016-04-21T13:01:52.507285 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::TerminationRequest:0x007ff9bd9a0650>
W, [2016-04-21T13:01:52.507369 #98370] WARN -- : Terminating task: type=:finalizer, meta={:dangerous_suspend=>true, :method_name=>:__shutdown__}, status=:receiving
Celluloid::Task::Fibered backtrace unavailable. Please try `Celluloid.task_class = Celluloid::Task::Threaded` if you need backtraces here.
D, [2016-04-21T13:01:52.507541 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::ExitEvent:0x007ff9bd9825d8>
D, [2016-04-21T13:01:52.507600 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::TerminationRequest:0x007ff9bd9a0678>
D, [2016-04-21T13:01:52.507742 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::ExitEvent:0x007ff9bd982bf0>
D, [2016-04-21T13:01:52.507786 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::ExitEvent:0x007ff9bd982e20>
D, [2016-04-21T13:01:52.508087 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::Call::Sync:0x007ff9bd981ea8>
D, [2016-04-21T13:01:52.508162 #98370] DEBUG -- : Discarded message (mailbox is dead): #<Celluloid::Future::Result:0x007ff9bd97b800>
/Users/klaaspieter/.rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in `sysread_nonblock': end of file reached (EOFError)
from /Users/klaaspieter/.rubies/ruby-2.3.0/lib/ruby/2.3.0/openssl/buffering.rb:178:in `read_nonblock'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:42:in `block in sysread'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:390:in `synchronize'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:40:in `sysread'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:129:in `readpartial'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:223:in `block in runloop'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in `loop'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/lowdown-0.3.1/lib/lowdown/connection.rb:221:in `runloop'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in `public_send'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in `dispatch'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/async.rb:7:in `dispatch'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in `block in dispatch'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in `block in task'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in `block in task'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in `block in initialize'
from /Users/klaaspieter/.gem/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in `block in create'
We are using a keep_alive: true connection, and seeing the following exceptions in production:
[APNS Connection#0x7f420591c910] Connecting...
[APNS Connection#0x7f420591c910] Connection established.
Actor crashed!
ArgumentError: this IO is already registered with selector
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:42:in register' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:42:in
wait'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/reactor.rb:26:in wait_writable' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io.rb:66:in
wait_writable'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:34:in wait_writable' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:64:in
rescue in block in syswrite'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:61:in block in syswrite' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:390:in
synchronize'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:59:in syswrite' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:356:in
do_write'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-io-0.17.3/lib/celluloid/io/stream.rb:287:in print' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:182:in
block in connect!'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:34:in block in emit' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:33:in
delete_if'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:33:in emit' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in
block in send_data'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in each' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in
send_data'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/connection.rb:346:in send' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/client.rb:38:in
send'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:34:in block in emit' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:33:in
delete_if'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/emitter.rb:33:in emit' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in
block in send_data'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in each' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/flow_buffer.rb:56:in
send_data'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/stream.rb:136:in send' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/http-2-0.8.2/lib/http/2/stream.rb:192:in
data'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:375:in try_to_perform_request!' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:326:in
request'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:312:in post' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in
public_send'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in dispatch' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:16:in
dispatch'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in block in dispatch' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in
block in task'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in block in task' /var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in
block in initialize'
/var/www/apps/push_app/shared/bundle/ruby/2.3.0/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in `block in create'
[APNS Connection#0x7f420591c910] Closing...
[APNS Connection#0x7f4208d0d760] Connecting...
[APNS Connection#0x7f41dd75f280] Connecting...
[APNS Connection#0x7f41dd75f280] Connection established.
[APNS Connection#0x7f4208d0d760] Connection established.
Not really an issue, but here goes.
In my app I generate and store a client per worker that is essentially client = Lowdown::Client.production(production_env, certificate: cert, pool_size: 3)
and then the worker essentially runs:
client.connect do |group|
tokens.each do |t|
notif = Lowdown::Notification.new( etc )
group.send_notification(notif) {}
end
end
But I believe that's disconnecting the client in the middle of the next group sending. I'm getting a few different errors, things like
ERROR -- : Lowdown::Connection::TimedOut: Initiating SSL socket timed-out. - retrying in 5 seconds (1/5)
ERROR -- : IOError: closed stream - retrying in 5 seconds (1/5)
ERROR -- : Actor crashed!
IOError: closed stream
Previously I had been connect
ing the client before storing it, which resulted in the CPU pegged at 100% constantly. My thought was to change from the block connect
to something like client.connect unless client.connection.connected?
with a disconnect
after the group is run, which prompted me to ask if I could tell if a connection was being used.
I'm starting to think maybe I'm not actually following how this is working. ๐
Can you add more details on what and how to generate the Apple certificate, we are having problems sending a message using the binary:
11:12 $ lowdown --topic io.greenhouse.Greenhouse --certificate certs/APNS/io_greenhouse_greenhouse_apns_prod_cert_combined.pem --alert 'Test lowdown' -e production XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
W, [2016-04-15T11:12:48.723000 #6022] WARN -- : [APNS Connection#0x1910] Defer performing request, because the connection has not been established yet.
E, [2016-04-15T11:12:49.023000 #6022] ERROR -- : [APNS Connection#0x1910] OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure - retrying in 5 seconds (1/5)
E, [2016-04-15T11:12:54.237000 #6022] ERROR -- : [APNS Connection#0x1910] OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure - retrying in 10 seconds (2/5)
E, [2016-04-15T11:13:04.454000 #6022] ERROR -- : [APNS Connection#0x1910] OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure - retrying in 15 seconds (3/5)
E, [2016-04-15T11:13:19.638000 #6022] ERROR -- : [APNS Connection#0x1910] OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure - retrying in 20 seconds (4/5)
E, [2016-04-15T11:13:39.880000 #6022] ERROR -- : [APNS Connection#0x1910] OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure - retrying in 25 seconds (5/5)
E, [2016-04-15T11:14:05.082000 #6022] ERROR -- : Actor crashed!
OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure
org/jruby/ext/openssl/SSLSocket.java:220:in `connect_nonblock'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-io-0.17.3/lib/celluloid/io/ssl_socket.rb:28:in `connect'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:175:in `block in connect!'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid.rb:414:in `block in timeout'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:255:in `timeout'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid.rb:413:in `timeout'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:175:in `connect!'
org/jruby/RubyKernel.java:1823:in `public_send'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28:in `dispatch'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/call/async.rb:7:in `dispatch'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in `block in dispatch'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in `block in task'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in `block in task'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in `block in initialize'
/Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in `block in create'
OpenSSL::SSL::SSLError: Received fatal alert: handshake_failure
connect_nonblock at org/jruby/ext/openssl/SSLSocket.java:220
connect at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-io-0.17.3/lib/celluloid/io/ssl_socket.rb:28
block in connect! at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:175
block in timeout at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid.rb:414
timeout at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:255
timeout at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid.rb:413
connect! at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/lowdown-0.3.2/lib/lowdown/connection.rb:175
public_send at org/jruby/RubyKernel.java:1823
dispatch at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/calls.rb:28
dispatch at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/call/async.rb:7
block in dispatch at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50
block in task at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76
block in task at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339
block in initialize at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/task.rb:44
block in create at /Users/orion.delwaterman/.rvm/gems/jruby-9.0.5.0/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14
First of, let me thank you for this awesome gem! It works like a charm.
I use the initializer method from the readme. But if I try to use the gem as part of a delayed job it seems to get stuck here:
https://github.com/alloy/lowdown/blob/master/lib/lowdown/client.rb#L97
This is probably a celluloid problem, right?
Any suggestion how to send the notifications asynchronous in the background?
iOS 10 added support for extended notification content. To support this, we need to set mutable-content to 1 in aps hash. Could you add mutable-content in the following array?
APS_KEYS = %w( alert badge sound content-available category mutable-content).freeze
Hey @alloy, thanks for the great project.
To give some context, I'm quite a ruby n00b, so apologies if anything in this issue seems a bit naive or ill-educated.
Whenever I create a persistent connection, my process freezes. I've reproduced this in irb
by simply creating a persistent connection. However, I can press CTL + C
to continue using irb
and send notifications over the connection.
My initialisation in irb
was:
client = Lowdown::Client.production(false,
certificate: File.read(/path/to/pem),
keep_alive: true)
My initialisation in my worker was:
def dev_pool
dev_pool = nil
dev_mutex.synchronize do
require 'lowdown' # <-- just-in-time loading of Lowdown
@dev_pool ||= Lowdown::Client.production(false,
certificate: File.read(ENV['APNS_DEV_PEM']),
pool_size: 3,
keep_alive: true)
dev_pool = @dev_pool
end
dev_pool
end
def prod_pool
prod_pool = nil
prod_mutex.synchronize do
require 'lowdown' # <-- just-in-time loading of Lowdown
@prod_pool ||= Lowdown::Client.production(true,
certificate: File.read(ENV['APNS_PROD_PEM']),
pool_size: 3,
keep_alive: true)
prod_pool = @prod_pool
end
prod_pool
end
The above is taken from previous issues I've seen in this repo.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.