render_sync 0.5.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 +7 -0
- data/CHANGELOG.md +153 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +521 -0
- data/Rakefile +9 -0
- data/app/assets/javascripts/sync.coffee +355 -0
- data/app/controllers/sync/refetches_controller.rb +56 -0
- data/app/helpers/render_sync/config_helper.rb +15 -0
- data/config/routes.rb +3 -0
- data/config/sync.yml +21 -0
- data/lib/generators/render_sync/install_generator.rb +14 -0
- data/lib/generators/render_sync/templates/sync.ru +14 -0
- data/lib/generators/render_sync/templates/sync.yml +34 -0
- data/lib/render_sync.rb +174 -0
- data/lib/render_sync/action.rb +39 -0
- data/lib/render_sync/actions.rb +114 -0
- data/lib/render_sync/channel.rb +23 -0
- data/lib/render_sync/clients/dummy.rb +22 -0
- data/lib/render_sync/clients/faye.rb +104 -0
- data/lib/render_sync/clients/pusher.rb +77 -0
- data/lib/render_sync/controller_helpers.rb +33 -0
- data/lib/render_sync/engine.rb +24 -0
- data/lib/render_sync/erb_tracker.rb +49 -0
- data/lib/render_sync/faye_extension.rb +45 -0
- data/lib/render_sync/model.rb +174 -0
- data/lib/render_sync/model_actions.rb +60 -0
- data/lib/render_sync/model_change_tracking.rb +97 -0
- data/lib/render_sync/model_syncing.rb +65 -0
- data/lib/render_sync/model_touching.rb +35 -0
- data/lib/render_sync/partial.rb +112 -0
- data/lib/render_sync/partial_creator.rb +47 -0
- data/lib/render_sync/reactor.rb +48 -0
- data/lib/render_sync/refetch_model.rb +21 -0
- data/lib/render_sync/refetch_partial.rb +43 -0
- data/lib/render_sync/refetch_partial_creator.rb +21 -0
- data/lib/render_sync/renderer.rb +19 -0
- data/lib/render_sync/resource.rb +115 -0
- data/lib/render_sync/scope.rb +113 -0
- data/lib/render_sync/scope_definition.rb +30 -0
- data/lib/render_sync/view_helpers.rb +106 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/sync/users/_show.html.erb +1 -0
- data/test/dummy/app/views/sync/users/refetch/_show.html.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +22 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +8 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/log/test.log +626 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/em_minitest_spec.rb +100 -0
- data/test/fixtures/sync_auth_token_missing.yml +6 -0
- data/test/fixtures/sync_erb.yml +7 -0
- data/test/fixtures/sync_faye.yml +7 -0
- data/test/fixtures/sync_pusher.yml +8 -0
- data/test/models/group.rb +3 -0
- data/test/models/project.rb +2 -0
- data/test/models/todo.rb +8 -0
- data/test/models/user.rb +82 -0
- data/test/sync/abstract_controller.rb +3 -0
- data/test/sync/action_test.rb +82 -0
- data/test/sync/channel_test.rb +15 -0
- data/test/sync/config_test.rb +25 -0
- data/test/sync/erb_tracker_test.rb +72 -0
- data/test/sync/faye_extension_test.rb +87 -0
- data/test/sync/message_test.rb +159 -0
- data/test/sync/model_test.rb +315 -0
- data/test/sync/partial_creator_test.rb +35 -0
- data/test/sync/partial_test.rb +107 -0
- data/test/sync/protected_attributes_test.rb +39 -0
- data/test/sync/reactor_test.rb +18 -0
- data/test/sync/refetch_model_test.rb +26 -0
- data/test/sync/refetch_partial_creator_test.rb +16 -0
- data/test/sync/refetch_partial_test.rb +74 -0
- data/test/sync/renderer_test.rb +19 -0
- data/test/sync/resource_test.rb +181 -0
- data/test/sync/scope_definition_test.rb +39 -0
- data/test/sync/scope_test.rb +113 -0
- data/test/test_helper.rb +66 -0
- data/test/travis/sync.ru +14 -0
- data/test/travis/sync.yml +21 -0
- metadata +317 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
def self.source_root
|
5
|
+
File.dirname(__FILE__) + "/templates"
|
6
|
+
end
|
7
|
+
|
8
|
+
def copy_files
|
9
|
+
template "sync.yml", "config/sync.yml"
|
10
|
+
copy_file "sync.ru", "sync.ru"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Run with: rackup sync.ru -E production
|
2
|
+
require "bundler/setup"
|
3
|
+
require "yaml"
|
4
|
+
require "faye"
|
5
|
+
require "render_sync"
|
6
|
+
|
7
|
+
Faye::WebSocket.load_adapter 'thin'
|
8
|
+
|
9
|
+
RenderSync.load_config(
|
10
|
+
File.expand_path("../config/sync.yml", __FILE__),
|
11
|
+
ENV["RAILS_ENV"] || "development"
|
12
|
+
)
|
13
|
+
|
14
|
+
run RenderSync.pubsub_app
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Faye
|
2
|
+
development:
|
3
|
+
server: "http://localhost:9292/faye"
|
4
|
+
adapter_javascript_url: "http://localhost:9292/faye/faye.js"
|
5
|
+
auth_token: DEVELOPMENT_SECRET_TOKEN
|
6
|
+
adapter: "Faye"
|
7
|
+
async: true
|
8
|
+
|
9
|
+
# Pusher
|
10
|
+
# development:
|
11
|
+
# adapter_javascript_url: "http://js.pusher.com/2.0/pusher.min.js"
|
12
|
+
# app_id: "YOUR_PUSHER_APP_ID"
|
13
|
+
# api_key: "YOUR_PUSHER_API_KEY"
|
14
|
+
# auth_token: "YOUR_PUSHER_SECRET"
|
15
|
+
# adapter: "Pusher"
|
16
|
+
# async: true
|
17
|
+
|
18
|
+
# Disabled
|
19
|
+
# development:
|
20
|
+
# adapter: false
|
21
|
+
|
22
|
+
test:
|
23
|
+
server: "http://localhost:9292/faye"
|
24
|
+
adapter_javascript_url: "http://localhost:9292/faye/faye.js"
|
25
|
+
adapter: "Faye"
|
26
|
+
auth_token: "secret"
|
27
|
+
async: false
|
28
|
+
|
29
|
+
production:
|
30
|
+
server: "http://example.com/faye"
|
31
|
+
adapter_javascript_url: "http://localhost:9292/faye/faye.js"
|
32
|
+
adapter: "Faye"
|
33
|
+
auth_token: "<%= defined?(SecureRandom) ? SecureRandom.hex(32) : ActiveSupport::SecureRandom.hex(32) %>"
|
34
|
+
async: true
|
data/lib/render_sync.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'monitor'
|
3
|
+
require 'digest/sha1'
|
4
|
+
require 'erb'
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/https'
|
7
|
+
require 'logger'
|
8
|
+
require 'render_sync/renderer'
|
9
|
+
require 'render_sync/actions'
|
10
|
+
require 'render_sync/action'
|
11
|
+
require 'render_sync/controller_helpers'
|
12
|
+
require 'render_sync/view_helpers'
|
13
|
+
require 'render_sync/model_change_tracking'
|
14
|
+
require 'render_sync/model_actions'
|
15
|
+
require 'render_sync/model_syncing'
|
16
|
+
require 'render_sync/model_touching'
|
17
|
+
require 'render_sync/model'
|
18
|
+
require 'render_sync/scope'
|
19
|
+
require 'render_sync/scope_definition'
|
20
|
+
require 'render_sync/refetch_model'
|
21
|
+
require 'render_sync/faye_extension'
|
22
|
+
require 'render_sync/partial_creator'
|
23
|
+
require 'render_sync/refetch_partial_creator'
|
24
|
+
require 'render_sync/partial'
|
25
|
+
require 'render_sync/refetch_partial'
|
26
|
+
require 'render_sync/channel'
|
27
|
+
require 'render_sync/resource'
|
28
|
+
require 'render_sync/clients/faye'
|
29
|
+
require 'render_sync/clients/pusher'
|
30
|
+
require 'render_sync/clients/dummy'
|
31
|
+
require 'render_sync/reactor'
|
32
|
+
if defined? Rails
|
33
|
+
require 'render_sync/erb_tracker'
|
34
|
+
require 'render_sync/engine'
|
35
|
+
end
|
36
|
+
|
37
|
+
module RenderSync
|
38
|
+
|
39
|
+
class << self
|
40
|
+
attr_accessor :config, :client, :logger
|
41
|
+
|
42
|
+
def config
|
43
|
+
@config || {}
|
44
|
+
end
|
45
|
+
|
46
|
+
def config_json
|
47
|
+
@config_json ||= begin
|
48
|
+
{
|
49
|
+
server: server,
|
50
|
+
api_key: api_key,
|
51
|
+
pusher_ws_host: pusher_ws_host,
|
52
|
+
pusher_ws_port: pusher_ws_port,
|
53
|
+
pusher_wss_port: pusher_wss_port,
|
54
|
+
pusher_encrypted: pusher_encrypted,
|
55
|
+
adapter: adapter
|
56
|
+
}.reject { |k, v| v.nil? }.to_json
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Resets the configuration to the default (empty hash)
|
61
|
+
def reset_config
|
62
|
+
@config = {}
|
63
|
+
@config_json = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Loads the configuration from a given YAML file and environment (such as production)
|
67
|
+
def load_config(filename, environment)
|
68
|
+
reset_config
|
69
|
+
yaml = YAML.load(ERB.new(File.read(filename)).result)[environment.to_s]
|
70
|
+
raise ArgumentError, "The #{environment} environment does not exist in #{filename}" if yaml.nil?
|
71
|
+
yaml.each{|key, value| config[key.to_sym] = value }
|
72
|
+
setup_logger
|
73
|
+
|
74
|
+
if adapter
|
75
|
+
setup_client
|
76
|
+
else
|
77
|
+
setup_dummy_client
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_client
|
82
|
+
raise ArgumentError, "auth_token missing" if config[:auth_token].nil?
|
83
|
+
@client = RenderSync::Clients.const_get(adapter).new
|
84
|
+
@client.setup
|
85
|
+
end
|
86
|
+
|
87
|
+
def setup_dummy_client
|
88
|
+
config[:auth_token] = 'dummy_auth_token'
|
89
|
+
@client = RenderSync::Clients::Dummy.new
|
90
|
+
end
|
91
|
+
|
92
|
+
def setup_logger
|
93
|
+
@logger = (defined?(Rails) && Rails.logger) ? Rails.logger : Logger.new(STDOUT)
|
94
|
+
end
|
95
|
+
|
96
|
+
def async?
|
97
|
+
config[:async]
|
98
|
+
end
|
99
|
+
|
100
|
+
def server
|
101
|
+
config[:server]
|
102
|
+
end
|
103
|
+
|
104
|
+
def adapter_javascript_url
|
105
|
+
config[:adapter_javascript_url]
|
106
|
+
end
|
107
|
+
|
108
|
+
def auth_token
|
109
|
+
config[:auth_token]
|
110
|
+
end
|
111
|
+
|
112
|
+
def adapter
|
113
|
+
config[:adapter]
|
114
|
+
end
|
115
|
+
|
116
|
+
def app_id
|
117
|
+
config[:app_id]
|
118
|
+
end
|
119
|
+
|
120
|
+
def api_key
|
121
|
+
config[:api_key]
|
122
|
+
end
|
123
|
+
|
124
|
+
def pusher_api_scheme
|
125
|
+
config[:pusher_api_scheme]
|
126
|
+
end
|
127
|
+
|
128
|
+
def pusher_api_host
|
129
|
+
config[:pusher_api_host]
|
130
|
+
end
|
131
|
+
|
132
|
+
def pusher_api_port
|
133
|
+
config[:pusher_api_port]
|
134
|
+
end
|
135
|
+
|
136
|
+
def pusher_ws_host
|
137
|
+
config[:pusher_ws_host]
|
138
|
+
end
|
139
|
+
|
140
|
+
def pusher_ws_port
|
141
|
+
config[:pusher_ws_port]
|
142
|
+
end
|
143
|
+
|
144
|
+
def pusher_wss_port
|
145
|
+
config[:pusher_wss_port]
|
146
|
+
end
|
147
|
+
|
148
|
+
def pusher_encrypted
|
149
|
+
if config[:pusher_encrypted].nil?
|
150
|
+
true
|
151
|
+
else
|
152
|
+
config[:pusher_encrypted]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def reactor
|
157
|
+
@reactor ||= Reactor.new
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the Faye Rack application.
|
161
|
+
# Any options given are passed to the Faye::RackAdapter.
|
162
|
+
def pubsub_app(options = {})
|
163
|
+
Faye::RackAdapter.new({
|
164
|
+
mount: config[:mount] || "/faye",
|
165
|
+
timeout: config[:timeout] || 45,
|
166
|
+
extensions: [FayeExtension.new]
|
167
|
+
}.merge(options))
|
168
|
+
end
|
169
|
+
|
170
|
+
def views_root
|
171
|
+
Rails.root.join('app', 'views', 'sync')
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RenderSync
|
2
|
+
class Action
|
3
|
+
include Actions
|
4
|
+
|
5
|
+
attr_accessor :record, :name, :scope
|
6
|
+
|
7
|
+
def initialize(record, name, *args)
|
8
|
+
options = args.extract_options!
|
9
|
+
@record = record
|
10
|
+
@name = name
|
11
|
+
@scope = get_scope_from_options(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform
|
15
|
+
case name
|
16
|
+
when :new
|
17
|
+
sync_new record, scope: scope
|
18
|
+
when :update
|
19
|
+
sync_update record, scope: scope
|
20
|
+
when :destroy
|
21
|
+
sync_destroy record, scope: scope
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Just for testing purposes (see test/sync/model_test.rb)
|
26
|
+
def test_path
|
27
|
+
Resource.new(record, scope).polymorphic_path.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Merge default_scope and scope from options Hash
|
33
|
+
# compact array to remove nil elements
|
34
|
+
def get_scope_from_options(options)
|
35
|
+
[options[:default_scope], options[:scope]].compact
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Actions
|
3
|
+
|
4
|
+
# Render all sync'd partials for resource to string and publish update action
|
5
|
+
# to pubsub server with rendered resource messages
|
6
|
+
#
|
7
|
+
# resource - The ActiveModel resource
|
8
|
+
# options - The Hash of options
|
9
|
+
# default_scope - The ActiveModel resource to scope the update channel to
|
10
|
+
# scope - Either a String, a symbol, an instance of ActiveModel or
|
11
|
+
# RenderSync::Scope or an Array containing a combination to scope
|
12
|
+
# the update channel to. Will be concatenated to an optional
|
13
|
+
# default_scope
|
14
|
+
#
|
15
|
+
def sync_update(resource, options = {})
|
16
|
+
sync resource, :update, options
|
17
|
+
end
|
18
|
+
|
19
|
+
# Render all sync'd partials for resource to string and publish destroy action
|
20
|
+
# to pubsub server with rendered resource messages
|
21
|
+
#
|
22
|
+
# resource - The ActiveModel resource
|
23
|
+
# options - The Hash of options
|
24
|
+
# default_scope - The ActiveModel resource to scope the update channel to
|
25
|
+
# scope - Either a String, a symbol, an instance of ActiveModel or
|
26
|
+
# RenderSync::Scope or an Array containing a combination to scope
|
27
|
+
# the destroy channel to. Will be concatenated to an optional
|
28
|
+
# default_scope
|
29
|
+
#
|
30
|
+
def sync_destroy(resource, options = {})
|
31
|
+
sync resource, :destroy, options
|
32
|
+
end
|
33
|
+
|
34
|
+
# Render all sync'd partials for resource to string and publish action
|
35
|
+
# to pubsub server with rendered resource messages
|
36
|
+
#
|
37
|
+
# resource - The ActiveModel resource
|
38
|
+
# action - The Symbol action to publish. One of :update, :destroy
|
39
|
+
# options - The Hash of options
|
40
|
+
# default_scope - The ActiveModel resource to scope the action channel to
|
41
|
+
# scope - Either a String, a symbol, an instance of ActiveModel or
|
42
|
+
# RenderSync::Scope or an Array containing a combination to scope
|
43
|
+
# the channel to. Will be concatenated to an optional default_scope
|
44
|
+
#
|
45
|
+
def sync(resource, action, options = {})
|
46
|
+
scope = options[:scope]
|
47
|
+
partial_name = options[:partial]
|
48
|
+
resources = [resource].flatten
|
49
|
+
messages = resources.collect do |resource|
|
50
|
+
if partial_name
|
51
|
+
specified_partials(resource, sync_render_context, partial_name).collect do |partial|
|
52
|
+
partial.message(action)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
all_partials(resource, sync_render_context, scope).collect do |partial|
|
56
|
+
partial.message(action)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
RenderSync.client.batch_publish(messages.flatten)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Render all sync'd partials for resource to string and publish
|
65
|
+
# new action to pubsub server with rendered resource messages
|
66
|
+
#
|
67
|
+
# resource - The ActiveModel resource, or Array of ActiveModel resources
|
68
|
+
# action - The Symbol action to publish. One of :update, :destroy
|
69
|
+
# options - The Hash of options
|
70
|
+
# default_scope - The ActiveModel resource to scope the new channel to
|
71
|
+
# scope - Either a String, a symbol, an instance of ActiveModel or
|
72
|
+
# RenderSync::Scope or an Array containing any combination to scope
|
73
|
+
# the new channel to. Will be concatenated to an optional
|
74
|
+
# default_scope
|
75
|
+
#
|
76
|
+
def sync_new(resource, options = {})
|
77
|
+
scope = options[:scope]
|
78
|
+
partial_name = options[:partial]
|
79
|
+
resources = [resource].flatten
|
80
|
+
messages = resources.collect do |resource|
|
81
|
+
if partial_name
|
82
|
+
specified_partials(resource, sync_render_context, partial_name).collect do |partial|
|
83
|
+
partial.creator_for_scope(scope).message
|
84
|
+
end
|
85
|
+
else
|
86
|
+
all_partials(resource, sync_render_context, scope).collect do |partial|
|
87
|
+
partial.creator_for_scope(scope).message
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
RenderSync.client.batch_publish(messages.flatten)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# The Context class handling partial rendering
|
98
|
+
def sync_render_context
|
99
|
+
@sync_render_context ||= Renderer.new
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns Array of Partials for all given resource and context, including
|
103
|
+
# both Partial and RefetchPartial instances
|
104
|
+
def all_partials(resource, context, scope = nil)
|
105
|
+
Partial.all(resource, context, scope) + RefetchPartial.all(resource, context, scope)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns an Array containing both the Partial and RefetchPartial instances
|
109
|
+
# for a given resource, context and partial name
|
110
|
+
def specified_partials(resource, context, partial_name)
|
111
|
+
[Partial.find(resource, partial_name, context), RefetchPartial.find(resource, partial_name, context)].compact
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RenderSync
|
2
|
+
|
3
|
+
class Channel
|
4
|
+
|
5
|
+
attr_accessor :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
self.name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def signature
|
12
|
+
OpenSSL::HMAC.hexdigest(
|
13
|
+
OpenSSL::Digest.new('sha1'),
|
14
|
+
RenderSync.auth_token,
|
15
|
+
self.name
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
RenderSync.client.normalize_channel(self.signature)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Clients
|
3
|
+
class Dummy
|
4
|
+
def method_missing(*args, &block)
|
5
|
+
nil
|
6
|
+
end
|
7
|
+
|
8
|
+
class Message
|
9
|
+
def self.method_missing(*args, &block)
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(*)
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(*args, &block)
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module RenderSync
|
2
|
+
module Clients
|
3
|
+
class Faye
|
4
|
+
|
5
|
+
def setup
|
6
|
+
require 'faye'
|
7
|
+
# nothing to set up
|
8
|
+
end
|
9
|
+
|
10
|
+
def batch_publish(*args)
|
11
|
+
Message.batch_publish(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_message(*args)
|
15
|
+
Message.new(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Public: Normalize channel to adapter supported format
|
19
|
+
#
|
20
|
+
# channel - The string channel name
|
21
|
+
#
|
22
|
+
# Returns The normalized channel prefixed with supported format for Faye
|
23
|
+
def normalize_channel(channel)
|
24
|
+
"/#{channel}"
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
class Message
|
29
|
+
|
30
|
+
attr_accessor :channel, :data
|
31
|
+
|
32
|
+
def self.batch_publish(messages)
|
33
|
+
if RenderSync.async?
|
34
|
+
batch_publish_asynchronous(messages)
|
35
|
+
else
|
36
|
+
batch_publish_synchronous(messages)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.batch_publish_synchronous(messages)
|
41
|
+
Net::HTTP.post_form(
|
42
|
+
URI.parse(RenderSync.server),
|
43
|
+
message: batch_messages_query_hash(messages).to_json
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.batch_publish_asynchronous(messages)
|
48
|
+
RenderSync.reactor.perform do
|
49
|
+
EM::HttpRequest.new(RenderSync.server).post(body: {
|
50
|
+
message: batch_messages_query_hash(messages).to_json
|
51
|
+
})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.batch_messages_query_hash(messages)
|
56
|
+
{
|
57
|
+
channel: "/batch_publish",
|
58
|
+
data: messages.collect(&:to_hash),
|
59
|
+
ext: { auth_token: RenderSync.auth_token }
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize(channel, data)
|
64
|
+
self.channel = channel
|
65
|
+
self.data = data
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_hash
|
69
|
+
{
|
70
|
+
channel: channel,
|
71
|
+
data: data,
|
72
|
+
ext: {
|
73
|
+
auth_token: RenderSync.auth_token
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_json
|
79
|
+
to_hash.to_json
|
80
|
+
end
|
81
|
+
|
82
|
+
def publish
|
83
|
+
if RenderSync.async?
|
84
|
+
publish_asynchronous
|
85
|
+
else
|
86
|
+
publish_synchronous
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def publish_synchronous
|
91
|
+
Net::HTTP.post_form URI.parse(RenderSync.server), message: to_json
|
92
|
+
end
|
93
|
+
|
94
|
+
def publish_asynchronous
|
95
|
+
RenderSync.reactor.perform do
|
96
|
+
EM::HttpRequest.new(RenderSync.server).post(body: {
|
97
|
+
message: self.to_json
|
98
|
+
})
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|