jason-rails 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +14 -5
  4. data/app/controllers/jason/api/pusher_controller.rb +15 -0
  5. data/app/controllers/jason/api_controller.rb +44 -2
  6. data/client/lib/JasonProvider.js +1 -1
  7. data/client/lib/createJasonReducers.js +7 -0
  8. data/client/lib/createPayloadHandler.d.ts +6 -3
  9. data/client/lib/createPayloadHandler.js +8 -4
  10. data/client/lib/createTransportAdapter.d.ts +5 -0
  11. data/client/lib/createTransportAdapter.js +20 -0
  12. data/client/lib/pruneIdsMiddleware.js +9 -11
  13. data/client/lib/transportAdapters/actionCableAdapter.d.ts +5 -0
  14. data/client/lib/transportAdapters/actionCableAdapter.js +35 -0
  15. data/client/lib/transportAdapters/pusherAdapter.d.ts +5 -0
  16. data/client/lib/transportAdapters/pusherAdapter.js +68 -0
  17. data/client/lib/useJason.js +14 -34
  18. data/client/lib/useJason.test.js +8 -2
  19. data/client/package.json +2 -1
  20. data/client/src/JasonProvider.tsx +1 -1
  21. data/client/src/createJasonReducers.ts +7 -0
  22. data/client/src/createPayloadHandler.ts +9 -4
  23. data/client/src/createTransportAdapter.ts +13 -0
  24. data/client/src/pruneIdsMiddleware.ts +11 -11
  25. data/client/src/restClient.ts +1 -0
  26. data/client/src/transportAdapters/actionCableAdapter.ts +38 -0
  27. data/client/src/transportAdapters/pusherAdapter.ts +72 -0
  28. data/client/src/useJason.test.ts +8 -2
  29. data/client/src/useJason.ts +15 -36
  30. data/client/yarn.lock +12 -0
  31. data/config/routes.rb +5 -1
  32. data/lib/jason.rb +29 -8
  33. data/lib/jason/broadcaster.rb +19 -0
  34. data/lib/jason/channel.rb +6 -2
  35. data/lib/jason/graph_helper.rb +165 -0
  36. data/lib/jason/includes_helper.rb +108 -0
  37. data/lib/jason/lua_generator.rb +23 -1
  38. data/lib/jason/publisher.rb +16 -16
  39. data/lib/jason/subscription.rb +208 -183
  40. data/lib/jason/version.rb +1 -1
  41. metadata +15 -2
@@ -1,17 +1,32 @@
1
1
  class Jason::Subscription
2
2
  attr_accessor :id, :config
3
+ attr_reader :includes_helper, :graph_helper
3
4
 
4
5
  def initialize(id: nil, config: nil)
5
6
  if id
6
7
  @id = id
7
8
  raw_config = $redis_jason.hgetall("jason:subscriptions:#{id}").map { |k,v| [k, JSON.parse(v)] }.to_h
9
+ raise "Subscription ID #{id} does not exist" if raw_config.blank?
8
10
  set_config(raw_config)
9
11
  else
10
12
  @id = Digest::MD5.hexdigest(config.sort_by { |key| key }.to_h.to_json)
11
- pp config.sort_by { |key| key }.to_h.to_json
12
13
  configure(config)
13
14
  end
14
- pp @id
15
+ @includes_helper = Jason::IncludesHelper.new({ model => self.config['includes'] })
16
+ @graph_helper = Jason::GraphHelper.new(self.id, @includes_helper)
17
+
18
+ check_for_missing_keys
19
+ end
20
+
21
+ def broadcaster
22
+ @broadcaster ||= Jason::Broadcaster.new(channel)
23
+ end
24
+
25
+ def check_for_missing_keys
26
+ missing_keys = includes_helper.all_models - Jason.schema.keys.map(&:to_s)
27
+ if missing_keys.present?
28
+ raise "#{missing_keys.inspect} are not in the schema. Only models in the Jason schema can be subscribed."
29
+ end
15
30
  end
16
31
 
17
32
  def self.upsert_by_config(model, conditions: {}, includes: {})
@@ -26,6 +41,13 @@ class Jason::Subscription
26
41
  self.new(id: id)
27
42
  end
28
43
 
44
+ def self.for_instance_with_child(model_name, id, child_model_name, include_all = true)
45
+ sub_ids = for_instance(model_name, id, include_all = true)
46
+ sub_ids.select do |sub_id|
47
+ find_by_id(sub_id).includes_helper.in_sub(model_name, child_model_name)
48
+ end
49
+ end
50
+
29
51
  def self.for_instance(model_name, id, include_all = true)
30
52
  subs = $redis_jason.smembers("jason:models:#{model_name}:#{id}:subscriptions")
31
53
  if include_all
@@ -41,37 +63,117 @@ class Jason::Subscription
41
63
 
42
64
  # Find and update subscriptions affected by a model changing foreign key
43
65
  # comment, comment_id, post, old_post_id, new_post_id
44
- def self.update_ids(model_name, id, parent_model_name, old_foreign_id, new_foreign_id)
45
- # Check if this change means it needs to be removed
46
- # First find subscriptions that reference this model
47
-
48
- if old_foreign_id
49
- old_model_subscriptions = for_instance(parent_model_name, old_foreign_id, false)
50
- new_model_subscriptions = for_instance(parent_model_name, new_foreign_id, false)
51
- else
52
- # If this is a new instance, we need to include _all_ subscriptions
53
- old_model_subscriptions = []
54
- new_model_subscriptions = for_instance(parent_model_name, new_foreign_id, true)
66
+ def self.update_ids(changed_model_name, changed_model_id, foreign_model_name, old_foreign_id, new_foreign_id)
67
+ # There are 4 cases to consider.
68
+ # changed_instance ---/--- foreign_instance
69
+ # \--+--- new_foreign_instance
70
+ #
71
+ # foreign instance can either be parent or child for a given subscription
72
+ # 1. Child swap/add: foreign is child
73
+ # 2. Stay in the family: foreign is parent + both old and new foreign instances are part of the sub
74
+ # 3. Join the family: foreign is parent + only new foreign instance are part of the sub
75
+ # 4. Leave the family: foreign is parent + only the old foreign instance is part of the sub
76
+
77
+ #########
78
+ # Subs where changed is parent
79
+ sub_ids = for_instance_with_child(changed_model_name, changed_model_id, foreign_model_name, true)
80
+ sub_ids.each do |sub_id|
81
+ subscription = find_by_id(sub_id)
82
+
83
+ # If foreign key has been nulled, nothing to add
84
+ add = new_foreign_id.present? ? [
85
+ {
86
+ model_names: [changed_model_name, foreign_model_name],
87
+ instance_ids: [[changed_model_id, new_foreign_id]]
88
+ },
89
+ # Add IDs of child models
90
+ subscription.load_ids_for_sub_models(foreign_model_name, new_foreign_id)
91
+ ] : nil
92
+
93
+ id_changeset = subscription.graph_helper.apply_update({
94
+ remove: [{
95
+ model_names: [changed_model_name, foreign_model_name],
96
+ instance_ids: [[changed_model_id, old_foreign_id]]
97
+ }],
98
+ add: add
99
+ })
100
+
101
+ subscription.apply_id_changeset(id_changeset)
102
+ subscription.broadcast_id_changeset(id_changeset)
55
103
  end
56
104
 
57
- # To add
58
- (new_model_subscriptions - old_model_subscriptions).each do |sub_id|
59
- # add the current ID to the subscription, then add the tree below it
60
- find_by_id(sub_id).set_id(model_name, id)
105
+ old_sub_ids = for_instance_with_child(foreign_model_name, old_foreign_id, changed_model_name, true)
106
+ new_sub_ids = for_instance_with_child(foreign_model_name, new_foreign_id, changed_model_name, true)
107
+
108
+ #########
109
+ # Subs where changed is child
110
+ # + parent in both old + new
111
+ # this is simple, only the edges need to change - no IDs can be changed
112
+ (old_sub_ids & new_sub_ids).each do |sub_id|
113
+ subscription = find_by_id(sub_id)
114
+ subscription.graph_helper.apply_update({
115
+ remove: [{
116
+ model_names: [changed_model_name, foreign_model_name],
117
+ instance_ids: [[changed_model_id, old_foreign_id]]
118
+ }],
119
+ add: [{
120
+ model_names: [changed_model_name, foreign_model_name],
121
+ instance_ids: [[changed_model_id, new_foreign_id]]
122
+ }]
123
+ })
61
124
  end
62
125
 
63
- # To remove
64
- (old_model_subscriptions - new_model_subscriptions).each do |sub_id|
65
- find_by_id(sub_id).remove_ids(model_name, [id])
126
+ #########
127
+ # Subs where changed is child
128
+ # + old parent wasn't in the sub, but new parent is
129
+ # IE the changed instance is joining the sub
130
+ # No edges are removed, just added
131
+ (new_sub_ids - old_sub_ids).each do |sub_id|
132
+ subscription = find_by_id(sub_id)
133
+ id_changeset = subscription.graph_helper.apply_update({
134
+ add: [
135
+ {
136
+ model_names: [changed_model_name, foreign_model_name],
137
+ instance_ids: [[changed_model_id, new_foreign_id]]
138
+ },
139
+ # Add IDs of child models
140
+ subscription.load_ids_for_sub_models(changed_model_name, changed_model_id)
141
+ ]
142
+ })
143
+
144
+ subscription.apply_id_changeset(id_changeset)
145
+ subscription.broadcast_id_changeset(id_changeset)
66
146
  end
67
147
 
68
- # TODO changes to sub models - e.g. post -> comment -> user
148
+ #########
149
+ # --> Leaving the family
150
+ # Subs where changed is child
151
+ # + old parent was in the sub, but new parent isn't
152
+ # Just need to remove the link, orphan detection will do the rest
153
+ (old_sub_ids - new_sub_ids).each do |sub_id|
154
+ subscription = find_by_id(sub_id)
155
+ id_changeset = subscription.graph_helper.apply_update({
156
+ remove: [
157
+ {
158
+ model_names: [changed_model_name, foreign_model_name],
159
+ instance_ids: [[changed_model_id, old_foreign_id]]
160
+ }
161
+ ]
162
+ })
163
+ subscription.apply_id_changeset(id_changeset)
164
+ subscription.broadcast_id_changeset(id_changeset)
165
+ end
69
166
  end
70
167
 
71
168
  def self.remove_ids(model_name, ids)
169
+ # td: finish this
72
170
  ids.each do |instance_id|
73
171
  for_instance(model_name, instance_id, false).each do |sub_id|
74
- find_by_id(sub_id).remove_ids(model_name, [instance_id])
172
+ subscription = find_by_id(sub_id)
173
+
174
+ id_changeset = subscription.graph_helper.apply_remove_node("#{model_name}:#{instance_id}")
175
+ subscription.apply_id_changeset(id_changeset)
176
+ subscription.broadcast_id_changeset(id_changeset)
75
177
  end
76
178
  end
77
179
  end
@@ -82,93 +184,25 @@ class Jason::Subscription
82
184
  end
83
185
 
84
186
  def self.all
85
- $redis_jason.keys('jason:subscriptions:*')
187
+ $redis_jason.smembers('jason:subscriptions').map { |id| Jason::Subscription.find_by_id(id) }
86
188
  end
87
189
 
88
190
  def set_config(raw_config)
89
- @config = raw_config.with_indifferent_access
90
- end
91
-
92
- # E.g. add comment#123, and then sub models
93
- def set_id(model_name, id)
94
- commit_ids(model_name, [id])
95
- assoc_name = get_assoc_name(model_name)
96
- set_ids_for_sub_models(assoc_name, [id])
191
+ @config = raw_config.deep_stringify_keys.deep_transform_values { |v| v.is_a?(Symbol) ? v.to_s : v }
97
192
  end
98
193
 
99
194
  def clear_id(model_name, id, parent_model_name)
100
195
  remove_ids(model_name, [id])
101
196
  end
102
197
 
103
- # Set the instance IDs for the subscription
104
- # Add an entry to the subscription list for each instance
105
- def set_ids(assoc_name = model, referrer_model_name = nil, referrer_ids = nil, enforce: false)
106
- model_name = assoc_name.to_s.singularize
107
-
108
- if referrer_model_name.blank? && conditions.blank?
109
- $redis_jason.sadd("jason:models:#{model_name}:all:subscriptions", id)
110
- ids = model_klass(model_name).all.pluck(:id)
111
- set_ids_for_sub_models(assoc_name, ids, enforce: enforce)
112
- return
113
- end
114
-
115
- if referrer_model_name.blank?
116
- ids = model_klass(model_name).where(conditions).pluck(:id)
117
- else
118
- assoc = model_klass(referrer_model_name).reflect_on_association(assoc_name.to_sym)
119
-
120
- if assoc.is_a?(ActiveRecord::Reflection::HasManyReflection)
121
- ids = model_klass(model_name).where(assoc.foreign_key => referrer_ids).pluck(:id)
122
- elsif assoc.is_a?(ActiveRecord::Reflection::BelongsToReflection)
123
- ids = model_klass(referrer_model_name).where(id: referrer_ids).pluck(assoc.foreign_key)
124
- end
125
- end
126
- return if ids.blank?
127
-
128
- enforce ? enforce_ids(model_name, ids) : commit_ids(model_name, ids)
129
- set_ids_for_sub_models(assoc_name, ids, enforce: enforce)
130
- end
131
-
132
- def refresh_ids(assoc_name = model, referrer_model_name = nil, referrer_ids)
133
-
134
- end
135
-
136
198
  # Add IDs that aren't present
137
199
  def commit_ids(model_name, ids)
138
- pp 'COMMIT'
139
- pp model_name
140
- pp ids
141
200
  $redis_jason.sadd("jason:subscriptions:#{id}:ids:#{model_name}", ids)
142
201
  ids.each do |instance_id|
143
202
  $redis_jason.sadd("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
144
203
  end
145
204
  end
146
205
 
147
- # Ensure IDs are _only_ the ones passed
148
- def enforce_ids(model_name, ids)
149
- old_ids = $redis_jason.smembers("jason:subscriptions:#{id}:ids:#{model_name}")
150
-
151
- # Remove
152
- ids_to_remove = old_ids - ids
153
- if ids_to_remove.present?
154
- $redis_jason.srem("jason:subscriptions:#{id}:ids:#{model_name}", ids_to_remove)
155
- end
156
-
157
- ids_to_remove.each do |instance_id|
158
- $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
159
- end
160
-
161
- # Add
162
- ids_to_add = ids - old_ids
163
- if ids_to_add.present?
164
- $redis_jason.sadd("jason:subscriptions:#{id}:ids:#{model_name}", ids_to_add)
165
- end
166
-
167
- ids_to_add.each do |instance_id|
168
- $redis_jason.sadd("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
169
- end
170
- end
171
-
172
206
  def remove_ids(model_name, ids)
173
207
  $redis_jason.srem("jason:subscriptions:#{id}:ids:#{model_name}", ids)
174
208
  ids.each do |instance_id|
@@ -176,108 +210,81 @@ class Jason::Subscription
176
210
  end
177
211
  end
178
212
 
179
- # 'posts', [post#1, post#2,...]
180
- def set_ids_for_sub_models(assoc_name, ids, enforce: false)
181
- model_name = assoc_name.to_s.singularize
182
- # Limitation: Same association can't appear twice
183
- includes_tree = get_tree_for(assoc_name)
213
+ def apply_id_changeset(changeset)
214
+ changeset[:ids_to_add].each do |model_name, ids|
215
+ commit_ids(model_name, ids)
216
+ end
184
217
 
185
- if includes_tree.is_a?(Hash)
186
- includes_tree.each do |assoc_name, includes_tree|
187
- set_ids(assoc_name, model_name, ids, enforce: enforce)
188
- end
189
- # [:likes, :user]
190
- elsif includes_tree.is_a?(Array)
191
- includes_tree.each do |assoc_name|
192
- set_ids(assoc_name, model_name, ids, enforce: enforce)
193
- end
194
- elsif includes_tree.is_a?(String)
195
- set_ids(includes_tree, model_name, ids, enforce: enforce)
218
+ changeset[:ids_to_remove].each do |model_name, ids|
219
+ remove_ids(model_name, ids)
196
220
  end
197
221
  end
198
222
 
199
- # assoc could be plural or not, so need to scan both.
200
- def get_assoc_name(model_name, haystack = includes)
201
- return model_name if model_name == model
202
-
203
- if haystack.is_a?(Hash)
204
- haystack.each do |assoc_name, includes_tree|
205
- if model_name.pluralize == assoc_name.to_s.pluralize
206
- return assoc_name
207
- else
208
- found_assoc = get_assoc_name(model_name, includes_tree)
209
- return found_assoc if found_assoc
210
- end
211
- end
212
- elsif haystack.is_a?(Array)
213
- haystack.each do |assoc_name|
214
- if model_name.pluralize == assoc_name.to_s.pluralize
215
- return assoc_name
216
- end
217
- end
218
- else
219
- if model_name.pluralize == haystack.to_s.pluralize
220
- return haystack
221
- end
223
+ def broadcast_id_changeset(changeset)
224
+ changeset[:ids_to_add].each do |model_name, ids|
225
+ ids.each { |id| add(model_name, id) }
222
226
  end
223
227
 
224
- return nil
228
+ changeset[:ids_to_remove].each do |model_name, ids|
229
+ ids.each { |id| destroy(model_name, id) }
230
+ end
225
231
  end
226
232
 
227
- def get_tree_for(needle, assoc_name = nil, haystack = includes)
228
- return includes if needle == model
229
- return haystack if needle.to_s == assoc_name.to_s
233
+ # Take a model name and IDs and return an edge set of all the models that appear and
234
+ # their instance IDs
235
+ def load_ids_for_sub_models(model_name, ids)
236
+ # Limitation: Same association can't appear twice
237
+ includes_tree = includes_helper.get_tree_for(model_name)
238
+ all_models = includes_helper.all_models(model_name)
239
+
240
+ relation = model_name.classify.constantize.all.eager_load(includes_tree)
230
241
 
231
- if haystack.is_a?(Hash)
232
- haystack.each do |assoc_name, includes_tree|
233
- found_haystack = get_tree_for(needle, assoc_name, includes_tree)
234
- return found_haystack if found_haystack
242
+ if model_name == model
243
+ if conditions.blank?
244
+ $redis_jason.sadd("jason:models:#{model_name}:all:subscriptions", id)
245
+ all_models -= [model_name]
246
+ else
247
+ relation = relation.where(conditions)
235
248
  end
249
+ else
250
+ raise "Must supply IDs for sub models" if ids.nil?
251
+ return if ids.blank?
252
+ relation = relation.where(id: ids)
236
253
  end
237
254
 
238
- return nil
239
- end
255
+ pluck_args = all_models.map { |m| "#{m.pluralize}.id" }
256
+ instance_ids = relation.pluck(*pluck_args)
240
257
 
241
- def all_models(tree = includes)
242
- sub_models = if tree.is_a?(Hash)
243
- tree.map do |k,v|
244
- [k, all_models(v)]
245
- end
246
- else
247
- tree
258
+ # pluck returns only a 1D array if only 1 arg passed
259
+ if all_models.size == 1
260
+ instance_ids = [instance_ids]
248
261
  end
249
262
 
250
- pp ([model] + [sub_models]).flatten.uniq.map(&:to_s).map(&:singularize)
251
- ([model] + [sub_models]).flatten.uniq.map(&:to_s).map(&:singularize)
263
+ return { model_names: all_models, instance_ids: instance_ids }
252
264
  end
253
265
 
254
- def clear_all_ids(assoc_name = model)
255
- model_name = assoc_name.to_s.singularize
256
- includes_tree = model_name == model ? includes : get_tree_for(assoc_name)
257
-
258
- if model_name == model && conditions.blank?
259
- $redis_jason.srem("jason:models:#{model_name}:all:subscriptions", id)
260
- end
266
+ # 'posts', [post#1, post#2,...]
267
+ def set_ids_for_sub_models(model_name = model, ids = nil, enforce: false)
268
+ edge_set = load_ids_for_sub_models(model_name, ids)
261
269
 
262
- ids = $redis_jason.smembers("jason:subscriptions:#{id}:ids:#{model_name}")
263
- ids.each do |instance_id|
264
- $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
265
- end
266
- $redis_jason.del("jason:subscriptions:#{id}:ids:#{model_name}")
270
+ # Build the tree
271
+ id_changeset = graph_helper.apply_update({
272
+ add: [edge_set]
273
+ })
274
+ apply_id_changeset(id_changeset)
275
+ end
267
276
 
268
- # Recursively clear IDs
269
- # { comments: [:like] }
270
- if includes_tree.is_a?(Hash)
271
- includes_tree.each do |assoc_name, includes_tree|
272
- clear_all_ids(assoc_name)
277
+ def clear_all_ids
278
+ includes_helper.all_models.each do |model_name|
279
+ if model_name == model && conditions.blank?
280
+ $redis_jason.srem("jason:models:#{model_name}:all:subscriptions", id)
273
281
  end
274
- # [:likes, :user]
275
- elsif includes_tree.is_a?(Array)
276
- includes_tree.each do |assoc_name|
277
- clear_all_ids(assoc_name)
282
+
283
+ ids = $redis_jason.smembers("jason:subscriptions:#{id}:ids:#{model_name}")
284
+ ids.each do |instance_id|
285
+ $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
278
286
  end
279
- elsif includes_tree.is_a?(String)
280
- clear_all_ids(includes_tree)
287
+ $redis_jason.del("jason:subscriptions:#{id}:ids:#{model_name}")
281
288
  end
282
289
  end
283
290
 
@@ -297,12 +304,9 @@ class Jason::Subscription
297
304
  @config['conditions']
298
305
  end
299
306
 
300
- def includes
301
- @config['includes']
302
- end
303
-
304
307
  def configure(raw_config)
305
308
  set_config(raw_config)
309
+ $redis_jason.sadd("jason:subscriptions", id)
306
310
  $redis_jason.hmset("jason:subscriptions:#{id}", *config.map { |k,v| [k, v.to_json] }.flatten)
307
311
  end
308
312
 
@@ -316,7 +320,7 @@ class Jason::Subscription
316
320
  $redis_jason.hset("jason:consumers", consumer_id, Time.now.utc)
317
321
 
318
322
  if before_consumer_count == 0
319
- set_ids
323
+ set_ids_for_sub_models
320
324
  end
321
325
  end
322
326
 
@@ -334,11 +338,17 @@ class Jason::Subscription
334
338
  end
335
339
 
336
340
  def channel
337
- "jason:#{id}"
341
+ "jason-#{id}"
342
+ end
343
+
344
+ def user_can_access?(user)
345
+ # td: implement the authorization logic here
346
+ return true if Jason.authorization_service.blank?
347
+ Jason.authorization_service.call(user, model, conditions, includes_helper.all_models - [model])
338
348
  end
339
349
 
340
350
  def get
341
- all_models.map { |model_name| get_for_model(model_name) }
351
+ includes_helper.all_models.map { |model_name| [model_name, get_for_model(model_name)] }.to_h
342
352
  end
343
353
 
344
354
  def get_for_model(model_name)
@@ -367,6 +377,21 @@ class Jason::Subscription
367
377
  }
368
378
  end
369
379
 
380
+ def add(model_name, instance_id)
381
+ idx = $redis_jason.incr("jason:subscription:#{id}:#{model_name}:idx")
382
+ payload = JSON.parse($redis_jason.hget("jason:cache:#{model_name}", instance_id) || '{}')
383
+
384
+ payload = {
385
+ id: instance_id,
386
+ model: model_name,
387
+ payload: payload,
388
+ md5Hash: id,
389
+ idx: idx.to_i
390
+ }
391
+
392
+ broadcaster.broadcast(payload)
393
+ end
394
+
370
395
  def update(model_name, instance_id, payload, gidx)
371
396
  idx = Jason::LuaGenerator.new.get_subscription(model_name, instance_id, id, gidx)
372
397
  return if idx.blank?
@@ -379,11 +404,11 @@ class Jason::Subscription
379
404
  idx: idx.to_i
380
405
  }
381
406
 
382
- ActionCable.server.broadcast(channel, payload)
407
+ broadcaster.broadcast(payload)
383
408
  end
384
409
 
385
410
  def destroy(model_name, instance_id)
386
- idx = $redis_jason.incr("jason:subscription:#{id}:#{model_name}idx")
411
+ idx = $redis_jason.incr("jason:subscription:#{id}:#{model_name}:idx")
387
412
 
388
413
  payload = {
389
414
  id: instance_id,
@@ -393,6 +418,6 @@ class Jason::Subscription
393
418
  idx: idx.to_i
394
419
  }
395
420
 
396
- ActionCable.server.broadcast(channel, payload)
421
+ broadcaster.broadcast(payload)
397
422
  end
398
423
  end