em_apn_manager 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ce5404fa96a8fb4011755d83fac888407fb0d459
4
- data.tar.gz: 2930eb22b3c1d7cd7affbafc2f938a9123ca3ae6
3
+ metadata.gz: 7488d9d6b4d3ffca37840e1efd52dd3bc555c4cb
4
+ data.tar.gz: 39053f313b6bdd6bb04469d2804c650ec0ca549f
5
5
  SHA512:
6
- metadata.gz: a1b5274c66621788d2b2991af6beff40cf4a2be3d93984c72b924af8f31bc9f0b316bfb32f7a3276b87b43431b055d09274143431e66d6b6c63adbe607397f09
7
- data.tar.gz: 560211b2323f0c76c3fedb45166761e87196d7941f67f0dfc010253324c01d265d6ec1d6495ea8c324d0795c5ecbc1d5ca2a6ad0418dd0384e3e72f1bb24e7be
6
+ metadata.gz: 4a9906727741db1583fe89b897c7876944a31ce5b0fa231c955195371e6f624ff633b3c606868aa47204a379933bf5ef6c3038952516ad2256e38a44d795786c
7
+ data.tar.gz: a0e2b04ee2a8d50f83d10931ddd6b94f9ac08051905ea1edb93a6c25a27c48ae412cf4177bf260d65908d16777f540ee24c28eaef06a630d0cf156fe040a3ca3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- em_apn_manager (0.0.2)
4
+ em_apn_manager (0.1.0)
5
5
  em-hiredis (>= 0.2.1)
6
6
  em_apn_manager
7
7
  eventmachine (>= 1.0.0)
data/README.md CHANGED
@@ -3,24 +3,40 @@ EventMachine APN Manager
3
3
 
4
4
  EventMachine APN Connection Manager, The purpose is to support multiple cert and multiple application with one process.
5
5
 
6
- Steps to use this gem.
7
- 1. Add `gem 'em_apn_manager', git: 'git@github.com:hlxwell/em_apn_manager.git'`
8
- 2. Run `bundle exec rails g event_machine:apn_manager:install` to generate 'config/em_apn_manager.yml' file.
9
- 3. Run `bundle exec em_apn_manager -e development`
10
- 4. Put this in your code
6
+ Steps for running with *Rails*:
7
+
8
+ 1. Add `gem 'em_apn_manager', git: 'git@github.com:hlxwell/em_apn_manager.git'` to *Gemfile*.
9
+
10
+ 2. Run `bundle exec rails g event_machine:apn_manager:install` to generate `config/em_apn_manager.yml` file.
11
+
12
+ 3. Run `bundle exec em_apn_manager server -e development`.
13
+
14
+
15
+ Steps for running `Standalone`:
16
+
17
+ 1. Run `gem install em_apn_manager`
18
+
19
+ 2. Run `em_apn_manager server --redis-host 127.0.0.1 --redis-port 6379` or `em_apn_manager server --config CONFIG_FILE_PATH`
20
+
21
+ Put below line to your code for sending push notification:
22
+
11
23
  `EM::ApnManager.push_notification({
12
- cert: READ_YOUR_CERT_CONTENT,
24
+ env: CERT_ENVIRONMENT,
25
+ cert: PEM_CERT_TEXT_CONTENT,
13
26
  token: DEVICE_TOKEN,
14
27
  message: YOUR_MESSAGE
15
28
  })`
16
29
 
30
+ Running server in background:
31
+
32
+ `em_apn_manager server --daemon`
17
33
 
18
34
  Generate pem from p12
19
35
  ==================
36
+
37
+ This is how you get `p12` file:
38
+ http://docs.urbanairship.com/build/ios.html#set-up-your-application-with-apple
39
+
20
40
  You have to convert p12 format to pem format by below command line.
21
41
  `openssl pkcs12 -in cert.p12 -out cert.pem -nodes -clcerts`
22
42
 
23
-
24
- TO DOs
25
- ==================
26
- 1. Implement running `bundle exec em_apn_manager -e development` in background, support `-daemon` and `-pid_file`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.1.0
data/bin/em_apn_manager CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+
2
3
  require 'em_apn_manager/cli'
3
4
 
5
+ ### When in development mode run this `ruby -Ilib ./bin/em_apn_manager`
4
6
  EM::ApnManager::CLI.start(ARGV)
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "em_apn_manager"
8
- s.version = "0.0.2"
8
+ s.version = "0.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael He"]
12
- s.date = "2013-07-16"
12
+ s.date = "2013-07-17"
13
13
  s.description = "EventMachine multiple APNs connections Management Solution. You can use multiple cert and connection to apple's APNs server."
14
14
  s.email = "m.he@skillupjapan.co.jp"
15
15
  s.executables = ["em_apn_manager"]
@@ -99,6 +99,16 @@ Gem::Specification.new do |s|
99
99
  s.add_development_dependency(%q<rdoc>, [">= 0"])
100
100
  s.add_development_dependency(%q<bundler>, [">= 0"])
101
101
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
102
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
103
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
104
+ s.add_development_dependency(%q<rdoc>, [">= 0"])
105
+ s.add_development_dependency(%q<bundler>, [">= 0"])
106
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
107
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
108
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
109
+ s.add_development_dependency(%q<rdoc>, [">= 0"])
110
+ s.add_development_dependency(%q<bundler>, [">= 0"])
111
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
102
112
  s.add_runtime_dependency(%q<thor>, ["~> 0.16"])
103
113
  s.add_runtime_dependency(%q<eventmachine>, [">= 1.0.0"])
104
114
  s.add_runtime_dependency(%q<yajl-ruby>, [">= 0.8.2"])
@@ -157,6 +167,16 @@ Gem::Specification.new do |s|
157
167
  s.add_dependency(%q<rdoc>, [">= 0"])
158
168
  s.add_dependency(%q<bundler>, [">= 0"])
159
169
  s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
170
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
171
+ s.add_dependency(%q<shoulda>, [">= 0"])
172
+ s.add_dependency(%q<rdoc>, [">= 0"])
173
+ s.add_dependency(%q<bundler>, [">= 0"])
174
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
175
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
176
+ s.add_dependency(%q<shoulda>, [">= 0"])
177
+ s.add_dependency(%q<rdoc>, [">= 0"])
178
+ s.add_dependency(%q<bundler>, [">= 0"])
179
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
160
180
  s.add_dependency(%q<thor>, ["~> 0.16"])
161
181
  s.add_dependency(%q<eventmachine>, [">= 1.0.0"])
162
182
  s.add_dependency(%q<yajl-ruby>, [">= 0.8.2"])
@@ -216,6 +236,16 @@ Gem::Specification.new do |s|
216
236
  s.add_dependency(%q<rdoc>, [">= 0"])
217
237
  s.add_dependency(%q<bundler>, [">= 0"])
218
238
  s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
239
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
240
+ s.add_dependency(%q<shoulda>, [">= 0"])
241
+ s.add_dependency(%q<rdoc>, [">= 0"])
242
+ s.add_dependency(%q<bundler>, [">= 0"])
243
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
244
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
245
+ s.add_dependency(%q<shoulda>, [">= 0"])
246
+ s.add_dependency(%q<rdoc>, [">= 0"])
247
+ s.add_dependency(%q<bundler>, [">= 0"])
248
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
219
249
  s.add_dependency(%q<thor>, ["~> 0.16"])
220
250
  s.add_dependency(%q<eventmachine>, [">= 1.0.0"])
221
251
  s.add_dependency(%q<yajl-ruby>, [">= 0.8.2"])
@@ -13,10 +13,11 @@ module EventMachine
13
13
  def push_notification options = {}
14
14
  # FIXME Check options
15
15
  $apn_manager_redis.publish "push-notification", {
16
+ env: options[:env],
16
17
  cert: options[:cert],
17
18
  token: options[:token],
18
19
  message: options[:message]
19
20
  }.to_json
20
21
  end
21
22
  end
22
- end
23
+ end
@@ -16,34 +16,48 @@ $apn_manager_redis = nil
16
16
  module EventMachine
17
17
  module ApnManager
18
18
  class CLI < Thor
19
- class_option :config, :aliases => ["-c"], :type => :string
20
- class_option :environment, :aliases => ["-e"], :type => :string
19
+ class_option :config, :aliases => ["-c"], :type => :string
20
+ class_option :environment, :aliases => ["-e"], :type => :string
21
+ class_option :redis, :aliases => ["-r"], :type => :string
21
22
 
23
+ ### 3 ways to specify the redis
24
+ # 1. config yml file
25
+ # 2. pass redis-url is 'redis://username:password@host:port/database'
26
+ # like `redis://test:test@localhost:6379/em_apn_manager`
27
+ #
22
28
  def initialize(args = [], opts = [], config = {})
23
29
  super(args, opts, config)
24
30
 
25
- # Read config option, or use default config yml
26
- config_path = options[:config] || File.join(".", "config", "em_apn_manager.yml")
27
- if config_path && File.exists?(config_path)
28
- EM::ApnManager.config = Thor::CoreExt::HashWithIndifferentAccess.new(YAML.load_file(config_path))
29
- else
30
- raise "No config file is specified or specified config file doesn't exist."
31
- end
31
+ redis_config = options[:redis]
32
+ if redis_config.nil?
33
+ # read the environment var.
34
+ @environment = ENV["RAILS_ENV"] || "development"
35
+ @environment = options[:environment] if %w{test development production}.include? options[:environment]
36
+
37
+ # Read config option, or use default config yml
38
+ config_path = options[:config] || File.join(".", "config", "em_apn_manager.yml")
39
+ if config_path && File.exists?(config_path)
40
+ EM::ApnManager.config = Thor::CoreExt::HashWithIndifferentAccess.new(YAML.load_file(config_path))
41
+ redis_config = EM::ApnManager.config[@environment]
42
+ end
32
43
 
33
- # read the environment var.
34
- @environment = "test"
35
- @environment = options[:environment] if %w{test development production}.include? options[:environment]
44
+ # default redis
45
+ redis_config ||= "redis://localhost:6379/em_apn_manager"
46
+ end
36
47
 
37
48
  # create redis connection
38
- $apn_manager_redis = Redis.new EM::ApnManager.config[@environment] || { host:"127.0.0.1", port:6379 }
49
+ $apn_manager_redis = Redis.new url: redis_config
39
50
  end
40
51
 
41
52
  desc "server", "Start manager server."
42
- # option :daemon, :aliases => ["-d"], :type => :boolean
43
- # option :pid_file, :aliases => ["-p"], :type => :string
53
+ option :daemon, :aliases => ["-d"], :type => :boolean
54
+ option :pid_file, :aliases => ["-p"], :type => :string
44
55
  def server
56
+ daemonize if options[:daemon]
57
+ write_pid_file(options[:pid_file]) if options[:pid_file]
58
+
45
59
  EM::ApnManager.logger.info("Starting APN Manager")
46
- EM.run { EM::ApnManager::Manager.run env: @environment }
60
+ EM.run { EM::ApnManager::Manager.run }
47
61
  end
48
62
 
49
63
  ### For Testing ##################################################
@@ -52,8 +66,9 @@ module EventMachine
52
66
  def push_test_message
53
67
  10.times do |i|
54
68
  EM::ApnManager.push_notification({
55
- cert: File.read(ENV["APN_CERT"]),
56
- token: ["0F93C49EAAF3544B5218D2BAE893608C515F69B445279AB2B17511C37046C52B","D42A6795D0C6C0E5F3CC762F905C3654D2A07E72D64CDEC1E2F74AC43C4CC440"].sample,
69
+ env: 'test',
70
+ cert: File.read(ENV["APN_CERT"]), # test cert
71
+ token: ["0F93C49EAAF3544B5218D2BAE893608C515F69B445279AB2B17511C37046C52B", "D42A6795D0C6C0E5F3CC762F905C3654D2A07E72D64CDEC1E2F74AC43C4CC440"].sample,
57
72
  message: "Hahahaha I am going to spam you. #{i}-#{rand * 100}"
58
73
  })
59
74
  end
@@ -64,6 +79,26 @@ module EventMachine
64
79
  EM::ApnManager.logger.info("Starting Mock APN Server")
65
80
  EM.run { EM.start_server("127.0.0.1", 2195, EM::ApnManager::ApnServer) }
66
81
  end
82
+
83
+ private
84
+
85
+ # Daemonize process (ruby >= 1.9 only)
86
+ # @return [void] Ruby ~>1.8
87
+ # @return [0] Ruby 1.9+ (see Process::daemon)
88
+ # @raise [Errno] on failure
89
+ def daemonize
90
+ if Process.respond_to?(:daemon)
91
+ Process.daemon(true, true)
92
+ else
93
+ Kernel.warn "Running process as daemon requires ruby >= 1.9"
94
+ end
95
+ end
96
+
97
+ # Save worker's pid to file
98
+ # @return [void]
99
+ def write_pid_file(path = nil)
100
+ File.open(path, 'w'){ |f| f << Process.pid } if path
101
+ end
67
102
  end
68
103
  end
69
104
  end
@@ -20,10 +20,10 @@ module EventMachine
20
20
  end
21
21
 
22
22
  def initialize(options = {})
23
- @cert = options[:cert] || ENV["APN_CERT"]
23
+ @cert = options[:cert]
24
24
  @port = options[:port] || PORT
25
25
  @environment = options[:env]
26
- @gateway = options[:gateway] || ENV["APN_GATEWAY"]
26
+ @gateway = options[:gateway]
27
27
  @gateway ||= case @environment
28
28
  when "test"
29
29
  TEST_GATEWAY
@@ -1,13 +1,3 @@
1
- production:
2
- host: localhost
3
- port: 6379
4
- db: YOUR_PRODUCTION_REDIS
5
- password: PASSWORD
6
-
7
- development:
8
- host: localhost
9
- port: 6379
10
-
11
- test:
12
- host: localhost
13
- port: 6379
1
+ production: redis://username:password@host:port/database
2
+ development: redis://localhost:6379/resque
3
+ test: redis://localhost:6379/resque
@@ -24,15 +24,17 @@ module EventMachine
24
24
 
25
25
  ### launch a new connect to apple when detected any pushs.
26
26
  @redis.pubsub.subscribe('push-notification') do |msg|
27
- msg_hash = Yajl::Parser.parse(msg) # might be some wrong json
27
+ msg_hash = Yajl::Parser.parse(msg) # FIXME might be some wrong json
28
+
28
29
  # save the cert to local first, since the start_tls read from file.
29
30
  cert_filename = save_cert_to_file msg_hash["cert"]
31
+
30
32
  # cert filename is a key for connection pool
31
33
  client = $connection_pool[cert_filename]
32
34
 
33
35
  ### Create client connection if doesn't exist in pool.
34
36
  if client.nil?
35
- client = EM::ApnManager::Client.new(options.merge!({cert: cert_filename}))
37
+ client = EM::ApnManager::Client.new(options.merge!({env: msg_hash["env"], cert: cert_filename}))
36
38
  # Store the connection to pool
37
39
  $connection_pool[cert_filename] = client
38
40
  end
@@ -54,8 +56,8 @@ module EventMachine
54
56
 
55
57
  private
56
58
 
59
+ # NOTICE should not put the 'certs' folder to a downloadable place.
57
60
  def save_cert_to_file cert_content
58
- # TODO, should store Rails.root/tmp/certs and this folder should be protected.
59
61
  FileUtils.mkdir_p "certs"
60
62
  filename = Base64.encode64(cert_content)[0..50]
61
63
  filename = File.join "certs", filename
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em_apn_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael He
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-16 00:00:00.000000000 Z
11
+ date: 2013-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em_apn_manager
@@ -724,6 +724,146 @@ dependencies:
724
724
  - - ~>
725
725
  - !ruby/object:Gem::Version
726
726
  version: 1.8.4
727
+ - !ruby/object:Gem::Dependency
728
+ name: rspec
729
+ requirement: !ruby/object:Gem::Requirement
730
+ requirements:
731
+ - - ~>
732
+ - !ruby/object:Gem::Version
733
+ version: 2.6.0
734
+ type: :development
735
+ prerelease: false
736
+ version_requirements: !ruby/object:Gem::Requirement
737
+ requirements:
738
+ - - ~>
739
+ - !ruby/object:Gem::Version
740
+ version: 2.6.0
741
+ - !ruby/object:Gem::Dependency
742
+ name: shoulda
743
+ requirement: !ruby/object:Gem::Requirement
744
+ requirements:
745
+ - - '>='
746
+ - !ruby/object:Gem::Version
747
+ version: '0'
748
+ type: :development
749
+ prerelease: false
750
+ version_requirements: !ruby/object:Gem::Requirement
751
+ requirements:
752
+ - - '>='
753
+ - !ruby/object:Gem::Version
754
+ version: '0'
755
+ - !ruby/object:Gem::Dependency
756
+ name: rdoc
757
+ requirement: !ruby/object:Gem::Requirement
758
+ requirements:
759
+ - - '>='
760
+ - !ruby/object:Gem::Version
761
+ version: '0'
762
+ type: :development
763
+ prerelease: false
764
+ version_requirements: !ruby/object:Gem::Requirement
765
+ requirements:
766
+ - - '>='
767
+ - !ruby/object:Gem::Version
768
+ version: '0'
769
+ - !ruby/object:Gem::Dependency
770
+ name: bundler
771
+ requirement: !ruby/object:Gem::Requirement
772
+ requirements:
773
+ - - '>='
774
+ - !ruby/object:Gem::Version
775
+ version: '0'
776
+ type: :development
777
+ prerelease: false
778
+ version_requirements: !ruby/object:Gem::Requirement
779
+ requirements:
780
+ - - '>='
781
+ - !ruby/object:Gem::Version
782
+ version: '0'
783
+ - !ruby/object:Gem::Dependency
784
+ name: jeweler
785
+ requirement: !ruby/object:Gem::Requirement
786
+ requirements:
787
+ - - ~>
788
+ - !ruby/object:Gem::Version
789
+ version: 1.8.4
790
+ type: :development
791
+ prerelease: false
792
+ version_requirements: !ruby/object:Gem::Requirement
793
+ requirements:
794
+ - - ~>
795
+ - !ruby/object:Gem::Version
796
+ version: 1.8.4
797
+ - !ruby/object:Gem::Dependency
798
+ name: rspec
799
+ requirement: !ruby/object:Gem::Requirement
800
+ requirements:
801
+ - - ~>
802
+ - !ruby/object:Gem::Version
803
+ version: 2.6.0
804
+ type: :development
805
+ prerelease: false
806
+ version_requirements: !ruby/object:Gem::Requirement
807
+ requirements:
808
+ - - ~>
809
+ - !ruby/object:Gem::Version
810
+ version: 2.6.0
811
+ - !ruby/object:Gem::Dependency
812
+ name: shoulda
813
+ requirement: !ruby/object:Gem::Requirement
814
+ requirements:
815
+ - - '>='
816
+ - !ruby/object:Gem::Version
817
+ version: '0'
818
+ type: :development
819
+ prerelease: false
820
+ version_requirements: !ruby/object:Gem::Requirement
821
+ requirements:
822
+ - - '>='
823
+ - !ruby/object:Gem::Version
824
+ version: '0'
825
+ - !ruby/object:Gem::Dependency
826
+ name: rdoc
827
+ requirement: !ruby/object:Gem::Requirement
828
+ requirements:
829
+ - - '>='
830
+ - !ruby/object:Gem::Version
831
+ version: '0'
832
+ type: :development
833
+ prerelease: false
834
+ version_requirements: !ruby/object:Gem::Requirement
835
+ requirements:
836
+ - - '>='
837
+ - !ruby/object:Gem::Version
838
+ version: '0'
839
+ - !ruby/object:Gem::Dependency
840
+ name: bundler
841
+ requirement: !ruby/object:Gem::Requirement
842
+ requirements:
843
+ - - '>='
844
+ - !ruby/object:Gem::Version
845
+ version: '0'
846
+ type: :development
847
+ prerelease: false
848
+ version_requirements: !ruby/object:Gem::Requirement
849
+ requirements:
850
+ - - '>='
851
+ - !ruby/object:Gem::Version
852
+ version: '0'
853
+ - !ruby/object:Gem::Dependency
854
+ name: jeweler
855
+ requirement: !ruby/object:Gem::Requirement
856
+ requirements:
857
+ - - ~>
858
+ - !ruby/object:Gem::Version
859
+ version: 1.8.4
860
+ type: :development
861
+ prerelease: false
862
+ version_requirements: !ruby/object:Gem::Requirement
863
+ requirements:
864
+ - - ~>
865
+ - !ruby/object:Gem::Version
866
+ version: 1.8.4
727
867
  - !ruby/object:Gem::Dependency
728
868
  name: thor
729
869
  requirement: !ruby/object:Gem::Requirement