juggernaut 0.5.4 → 2.1.1

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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/README ADDED
@@ -0,0 +1,8 @@
1
+ = Juggernaut
2
+
3
+ See http://github.com/maccman/juggernaut
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2010 Alex MacCaw.
8
+ See http://github.com/maccman/juggernaut/blob/master/LICENSE for details.
data/Rakefile CHANGED
@@ -1,19 +1,18 @@
1
- # -*- ruby -*-
2
-
3
1
  require 'rubygems'
4
- require 'hoe'
5
- require './lib/juggernaut.rb'
6
-
7
- Hoe.new('juggernaut', Juggernaut::VERSION) do |p|
8
- p.rubyforge_name = 'juggernaut'
9
- p.author = 'Alex MacCaw'
10
- p.email = 'info@eribium.org'
11
- # p.summary = 'FIX'
12
- # p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
13
- p.url = 'http://juggernaut.rubyforge.org'
14
- p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
- p.extra_deps << ['eventmachine', '>=0.10.0']
16
- p.extra_deps << ['json', '>=1.1.2']
17
- end
2
+ require 'rake'
18
3
 
19
- # vim: syntax=Ruby
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "juggernaut"
8
+ gem.summary = %Q{Simple realtime push}
9
+ gem.description = %Q{Use Juggernaut to easily implement realtime chat, collaboration, gaming and much more!}
10
+ gem.email = "info@eribium.org"
11
+ gem.homepage = "http://github.com/maccman/juggernaut"
12
+ gem.authors = ["Alex MacCaw"]
13
+ gem.add_dependency "redis", ">= 0"
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.1.1
@@ -0,0 +1,22 @@
1
+ // Assumes you're using SuperModel
2
+ // http://github.com/maccman/supermodel-js
3
+
4
+ jQuery(function($){
5
+ var jug = new Juggernaut;
6
+ jug.subscribe("/sync/your_user_id", function(sync){
7
+ var klass = eval(sync.klass);
8
+ switch(sync.type) {
9
+ case "create":
10
+ klass.create(sync.record);
11
+ break;
12
+ case "update":
13
+ klass.update(sync.id, sync.record);
14
+ break;
15
+ case "destroy":
16
+ klass.destroy(sync.id);
17
+ break;
18
+ default:
19
+ throw("Unknown type:" + type);
20
+ }
21
+ });
22
+ })
@@ -0,0 +1,24 @@
1
+ class JuggernautObserver < ActiveRecord::Observer
2
+ observe :activity, :user
3
+
4
+ def after_create(rec)
5
+ publish(:create, rec)
6
+ end
7
+
8
+ def after_update(rec)
9
+ publish(:update, rec)
10
+ end
11
+
12
+ def after_destroy(rec)
13
+ publish(:destroy, rec)
14
+ end
15
+
16
+ protected
17
+ def publish(type, rec)
18
+ Juggernaut.publish(
19
+ Array(rec.sync_clients).map {|c| "/sync/#{c}" },
20
+ {:type => type, :id => rec.id,
21
+ :klass => rec.class.name, :record => rec}
22
+ )
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ clients = {}
2
+
3
+ Juggernaut.subscribe do |event, data|
4
+ case event
5
+ when :subscribe
6
+ clients[data.session_id] = data
7
+ when :unsubscribe
8
+ clients.delete(data.session_id)
9
+ end
10
+ end
@@ -0,0 +1,48 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{juggernaut}
8
+ s.version = "2.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Alex MacCaw}]
12
+ s.date = %q{2012-01-03}
13
+ s.description = %q{Use Juggernaut to easily implement realtime chat, collaboration, gaming and much more!}
14
+ s.email = %q{info@eribium.org}
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "README",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "examples/juggernaut_observer.js",
22
+ "examples/juggernaut_observer.rb",
23
+ "examples/roster.rb",
24
+ "juggernaut.gemspec",
25
+ "lib/juggernaut.rb",
26
+ "lib/juggernaut/rails/engine.rb",
27
+ "vendor/assets/javascripts/json.js",
28
+ "vendor/assets/javascripts/juggernaut.js",
29
+ "vendor/assets/javascripts/socket_io.js"
30
+ ]
31
+ s.homepage = %q{http://github.com/maccman/juggernaut}
32
+ s.require_paths = [%q{lib}]
33
+ s.rubygems_version = %q{1.8.6}
34
+ s.summary = %q{Simple realtime push}
35
+
36
+ if s.respond_to? :specification_version then
37
+ s.specification_version = 3
38
+
39
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
40
+ s.add_runtime_dependency(%q<redis>, [">= 0"])
41
+ else
42
+ s.add_dependency(%q<redis>, [">= 0"])
43
+ end
44
+ else
45
+ s.add_dependency(%q<redis>, [">= 0"])
46
+ end
47
+ end
48
+
@@ -0,0 +1,7 @@
1
+ module Juggernaut
2
+ begin
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ rescue NameError
6
+ end
7
+ end
data/lib/juggernaut.rb CHANGED
@@ -1,152 +1,49 @@
1
- require 'logger'
2
- require 'eventmachine'
3
- require 'json'
4
- $:.unshift(File.dirname(__FILE__))
1
+ require "redis"
2
+ require "json"
5
3
 
6
- module Juggernaut
7
- VERSION = '0.5.4'
4
+ # Attempt to provide Engine to Rails
5
+ require "juggernaut/rails/engine"
8
6
 
9
- class JuggernautError < StandardError #:nodoc:
7
+ module Juggernaut
8
+ EVENTS = [
9
+ "juggernaut:subscribe",
10
+ "juggernaut:unsubscribe",
11
+ "juggernaut:custom"
12
+ ]
13
+
14
+ def options
15
+ @options ||= {}
10
16
  end
11
-
12
- @@options = {}
13
17
 
14
- DEFAULT_CONFIG_FILE = <<-EOF
15
- # ======================
16
- # Juggernaut Options
17
- # ======================
18
-
19
- # === Subscription authentication ===
20
- # Leave all subscription options uncommented to allow anyone to subscribe.
21
-
22
- # If specified, subscription_url is called everytime a client subscribes.
23
- # Parameters passed are: session_id, client_id and an array of channels.
24
- #
25
- # The server should check that the session_id matches up to the client_id
26
- # and that the client is allowed to access the specified channels.
27
- #
28
- # If a status code other than 200 is encountered, the subscription_request fails
29
- # and the client is disconnected.
30
- #
31
- # :subscription_url: http://localhost:3000/sessions/juggernaut_subscription
32
-
33
- # === Broadcast and query authentication ===
34
- # Leave all broadcast/query options uncommented to allow anyone to broadcast/query.
35
- #
36
- # Broadcast authentication in a production environment is very importantant since broadcasters
37
- # can execute JavaScript on subscribed clients, leaving you vulnerable to cross site scripting
38
- # attacks if broadcasters aren't authenticated.
39
-
40
- # 1) Via IP address
41
- #
42
- # If specified, if a client has an ip that is specified in allowed_ips, than it is automatically
43
- # authenticated, even if a secret_key isn't provided.
44
- #
45
- # This is the recommended method for broadcast authentication.
46
- #
47
- :allowed_ips:
48
- - 127.0.0.1
49
- # - 192.168.0.1
50
-
51
- # 2) Via HTTP request
52
- #
53
- # If specified, if a client attempts a broadcast/query, without a secret_key or using an IP
54
- # no included in allowed_ips, then broadcast_query_login_url will be called.
55
- # Parameters passed, if given, are: session_id, client_id, channels and type.
56
- #
57
- # The server should check that the session_id matches up to the client id, and the client
58
- # is allowed to perform that particular type of broadcast/query.
59
- #
60
- # If a status code other than 200 is encountered, the broadcast_query_login_url fails
61
- # and the client is disconnected.
62
- #
63
- # :broadcast_query_login_url: http://localhost:3000/sessions/juggernaut_broadcast
64
-
65
- # 3) Via shared secret key
66
- #
67
- # This secret key must be sent with any query/broadcast commands.
68
- # It must be the same as the one in the Rails config file.
69
- #
70
- # You shouldn't authenticate broadcasts from subscribed clients using this method
71
- # since the secret_key will be easily visible in the page (and not so secret any more)!
72
- #
73
- # :secret_key: your_secret_key_here
74
-
75
- # == Subscription Logout ==
76
-
77
- # If specified, logout_connection_url is called everytime a specific connection from a subscribed client disconnects.
78
- # Parameters passed are session_id, client_id and an array of channels specific to that connection.
79
- #
80
- # :logout_connection_url: http://localhost:3000/sessions/juggernaut_connection_logout
81
-
82
- # Logout url is called when all connections from a subscribed client are closed.
83
- # Parameters passed are session_id and client_id.
84
- #
85
- # :logout_url: http://localhost:3000/sessions/juggernaut_logout
86
-
87
- # === Miscellaneous ===
88
-
89
- # timeout defaults to 10. A timeout is the time between when a client closes a connection
90
- # and a logout_request or logout_connection_request is made. The reason for this is that a client
91
- # may only temporarily be disconnected, and may attempt a reconnect very soon.
92
- #
93
- # :timeout: 10
94
-
95
- # store_messages defaults to false. If this option is true, messages send to connections will be stored.
96
- # This is useful since a client can then receive broadcasted message that it has missed (perhaps it was disconnected).
97
- #
98
- # :store_messages: false
99
-
100
- # === Server ===
101
-
102
- # Host defaults to "0.0.0.0". You shouldn't need to change this.
103
- # :host: 0.0.0.0
104
-
105
- # Port is mandatory
106
- :port: 5001
107
-
108
- # Defaults to value of :port. If you are doing port forwarding you'll need to configure this to the same
109
- # value as :public_port in the juggernaut_hosts.yml file
110
- # :public_port: 5001
111
-
112
- EOF
113
-
114
- class << self
115
- def options
116
- @@options
117
- end
118
-
119
- def options=(val)
120
- @@options = val
121
- end
122
-
123
- def logger
124
- return @@logger if defined?(@@loggger)
125
- FileUtils.mkdir_p(File.dirname(log_path))
126
- @@logger = Logger.new(log_path)
127
- @@logger.level = Logger::INFO if options[:debug] == false
128
- @@logger
129
- rescue
130
- @@logger = Logger.new(STDOUT)
131
- end
132
-
133
- def log_path
134
- options[:log_path] || File.join(%w( / var run juggernaut.log ))
135
- end
136
-
137
- def pid_path
138
- options[:pid_path] || File.join(%w( / var run ), "juggernaut.#{options[:port]}.pid" )
139
- end
140
-
141
- def config_path
142
- options[:config_path] || File.join(%w( / var run juggernaut.yml ))
18
+ def options=(val)
19
+ @options = val
20
+ end
21
+
22
+ def url=(url)
23
+ options[:url] = url
24
+ end
25
+
26
+ def publish(channels, data, options = {})
27
+ message = ({:channels => Array(channels).uniq, :data => data}).merge(options)
28
+ redis.publish(key, message.to_json)
29
+ end
30
+
31
+ def subscribe
32
+ Redis.connect(options).subscribe(*EVENTS) do |on|
33
+ on.message do |type, msg|
34
+ yield(type.gsub(/^juggernaut:/, "").to_sym, JSON.parse(msg))
143
35
  end
36
+ end
144
37
  end
145
- end
38
+
39
+ protected
40
+ def redis
41
+ @redis ||= Redis.connect(options)
42
+ end
43
+
44
+ def key(*args)
45
+ args.unshift(:juggernaut).join(":")
46
+ end
146
47
 
147
- require 'juggernaut/utils'
148
- require 'juggernaut/miscel'
149
- require 'juggernaut/message'
150
- require 'juggernaut/client'
151
- require 'juggernaut/server'
152
- require 'juggernaut/runner'
48
+ extend self
49
+ end