jason-rails 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/Gemfile.lock +152 -2
  4. data/app/controllers/jason/api_controller.rb +1 -1
  5. data/client/lib/JasonContext.d.ts +6 -1
  6. data/client/lib/JasonProvider.d.ts +2 -2
  7. data/client/lib/JasonProvider.js +5 -124
  8. data/client/lib/createJasonReducers.js +41 -3
  9. data/client/lib/createOptDis.js +0 -2
  10. data/client/lib/createPayloadHandler.d.ts +6 -1
  11. data/client/lib/createPayloadHandler.js +42 -54
  12. data/client/lib/createServerActionQueue.d.ts +10 -0
  13. data/client/lib/createServerActionQueue.js +48 -0
  14. data/client/lib/createServerActionQueue.test.d.ts +1 -0
  15. data/client/lib/createServerActionQueue.test.js +37 -0
  16. data/client/lib/index.d.ts +3 -2
  17. data/client/lib/pruneIdsMiddleware.d.ts +2 -0
  18. data/client/lib/pruneIdsMiddleware.js +26 -0
  19. data/client/lib/restClient.d.ts +2 -0
  20. data/client/lib/restClient.js +17 -0
  21. data/client/lib/useJason.d.ts +5 -0
  22. data/client/lib/useJason.js +99 -0
  23. data/client/lib/useJason.test.d.ts +1 -0
  24. data/client/lib/useJason.test.js +79 -0
  25. data/client/lib/useSub.js +1 -0
  26. data/client/package.json +4 -3
  27. data/client/src/JasonProvider.tsx +5 -123
  28. data/client/src/createJasonReducers.ts +49 -3
  29. data/client/src/createOptDis.ts +0 -2
  30. data/client/src/createPayloadHandler.ts +47 -63
  31. data/client/src/createServerActionQueue.test.ts +42 -0
  32. data/client/src/createServerActionQueue.ts +47 -0
  33. data/client/src/pruneIdsMiddleware.ts +24 -0
  34. data/client/src/restClient.ts +13 -0
  35. data/client/src/useJason.test.ts +81 -0
  36. data/client/src/useJason.ts +115 -0
  37. data/client/src/useSub.ts +1 -0
  38. data/client/yarn.lock +59 -3
  39. data/jason-rails.gemspec +4 -0
  40. data/lib/jason.rb +12 -0
  41. data/lib/jason/api_model.rb +2 -12
  42. data/lib/jason/channel.rb +43 -21
  43. data/lib/jason/lua_generator.rb +49 -0
  44. data/lib/jason/publisher.rb +76 -35
  45. data/lib/jason/publisher_old.rb +112 -0
  46. data/lib/jason/subscription.rb +322 -99
  47. data/lib/jason/subscription_old.rb +171 -0
  48. data/lib/jason/version.rb +1 -1
  49. metadata +67 -3
@@ -0,0 +1,112 @@
1
+ module Jason::PublisherOld
2
+ extend ActiveSupport::Concern
3
+
4
+ def cache_json
5
+ as_json_config = api_model.as_json_config
6
+ scope = api_model.scope
7
+
8
+ if self.persisted? && (scope.blank? || self.class.unscoped.send(scope).exists?(self.id))
9
+ payload = self.reload.as_json(as_json_config)
10
+ $redis_jason.hset("jason:#{self.class.name.underscore}:cache", self.id, payload.to_json)
11
+ else
12
+ $redis_jason.hdel("jason:#{self.class.name.underscore}:cache", self.id)
13
+ end
14
+ end
15
+
16
+ def publish_json
17
+ cache_json
18
+ return if skip_publish_json
19
+
20
+ self.class.jason_subscriptions.each do |id, config_json|
21
+ config = JSON.parse(config_json)
22
+
23
+ if (config['conditions'] || {}).all? { |field, value| self.send(field) == value }
24
+ Jason::Subscription.new(id: id).update(self.class.name.underscore)
25
+ end
26
+ end
27
+ end
28
+
29
+ def publish_json_if_changed
30
+ subscribed_fields = api_model.subscribed_fields
31
+ publish_json if (self.previous_changes.keys.map(&:to_sym) & subscribed_fields).present? || !self.persisted?
32
+ end
33
+
34
+ class_methods do
35
+ def subscriptions
36
+ $redis_jason.hgetall("jason:#{self.name.underscore}:subscriptions")
37
+ end
38
+
39
+ def jason_subscriptions
40
+ $redis_jason.hgetall("jason:#{self.name.underscore}:subscriptions")
41
+ end
42
+
43
+ def publish_all(instances)
44
+ instances.each(&:cache_json)
45
+
46
+ subscriptions.each do |id, config_json|
47
+ Jason::Subscription.new(id: id).update(self.name.underscore)
48
+ end
49
+ end
50
+
51
+ def flush_cache
52
+ $redis_jason.del("jason:#{self.name.underscore}:cache")
53
+ end
54
+
55
+ def setup_json
56
+ self.after_initialize -> {
57
+ @api_model = Jason::ApiModel.new(self.class.name.underscore)
58
+ }
59
+ self.after_commit :publish_json_if_changed
60
+
61
+ include_models = Jason::ApiModel.new(self.name.underscore).include_models
62
+
63
+ include_models.map do |assoc|
64
+ puts assoc
65
+ reflection = self.reflect_on_association(assoc.to_sym)
66
+ reflection.klass.after_commit -> {
67
+ subscribed_fields = Jason::ApiModel.new(self.class.name.underscore).subscribed_fields
68
+ puts subscribed_fields.inspect
69
+
70
+ if (self.previous_changes.keys.map(&:to_sym) & subscribed_fields).present?
71
+ self.send(reflection.inverse_of.name)&.publish_json
72
+ end
73
+ }
74
+ end
75
+ end
76
+
77
+ def find_or_create_by_id(params)
78
+ object = find_by(id: params[:id])
79
+
80
+ if object
81
+ object.update(params)
82
+ elsif params[:hidden]
83
+ return false ## If an object is passed with hidden = true but didn't already exist, it's safe to never create it
84
+ else
85
+ object = create!(params)
86
+ end
87
+
88
+ object
89
+ end
90
+
91
+ def find_or_create_by_id!(params)
92
+ object = find_by(id: params[:id])
93
+
94
+ if object
95
+ object.update!(params)
96
+ elsif params[:hidden]
97
+ ## TODO: We're diverging from semantics of the Rails bang! methods here, which would normally either raise or return an object. Find a way to make this better.
98
+ return false ## If an object is passed with hidden = true but didn't already exist, it's safe to never create it
99
+ else
100
+ object = create!(params)
101
+ end
102
+
103
+ object
104
+ end
105
+ end
106
+
107
+ included do
108
+ attr_accessor :skip_publish_json, :api_model
109
+
110
+ setup_json
111
+ end
112
+ end
@@ -4,166 +4,389 @@ class Jason::Subscription
4
4
  def initialize(id: nil, config: nil)
5
5
  if id
6
6
  @id = id
7
- raw_config = $redis_jason.hgetall("jason:subscriptions:#{id}").map { |k,v| [k, JSON.parse(v)] }.to_h.with_indifferent_access
7
+ raw_config = $redis_jason.hgetall("jason:subscriptions:#{id}").map { |k,v| [k, JSON.parse(v)] }.to_h
8
8
  set_config(raw_config)
9
9
  else
10
- @id = Digest::MD5.hexdigest(config.to_json)
10
+ @id = Digest::MD5.hexdigest(config.sort_by { |key| key }.to_h.to_json)
11
+ pp config.sort_by { |key| key }.to_h.to_json
11
12
  configure(config)
12
13
  end
14
+ pp @id
13
15
  end
14
16
 
15
- def set_config(raw_config)
16
- @config = raw_config.with_indifferent_access.map { |k,v| [k.underscore.to_s, v] }.to_h
17
+ def self.upsert_by_config(model, conditions: {}, includes: {})
18
+ self.new(config: {
19
+ model: model,
20
+ conditions: conditions || {},
21
+ includes: includes || {}
22
+ })
17
23
  end
18
24
 
19
- def configure(raw_config)
20
- set_config(raw_config)
21
- $redis_jason.hmset("jason:subscriptions:#{id}", *config.map { |k,v| [k, v.to_json]}.flatten)
25
+ def self.find_by_id(id)
26
+ self.new(id: id)
22
27
  end
23
28
 
24
- def destroy
25
- config.each do |model, value|
26
- $redis_jason.srem("jason:#{model.to_s.underscore}:subscriptions", id)
29
+ def self.for_instance(model_name, id, include_all = true)
30
+ subs = $redis_jason.smembers("jason:models:#{model_name}:#{id}:subscriptions")
31
+ if include_all
32
+ subs += $redis_jason.smembers("jason:models:#{model_name}:all:subscriptions")
27
33
  end
28
- $redis_jason.del("jason:subscriptions:#{id}")
34
+
35
+ subs
29
36
  end
30
37
 
31
- def add_consumer(consumer_id)
32
- before_consumer_count = consumer_count
33
- $redis_jason.sadd("jason:subscriptions:#{id}:consumers", consumer_id)
34
- $redis_jason.hset("jason:consumers", consumer_id, Time.now.utc)
38
+ def self.for_model(model_name)
35
39
 
36
- add_subscriptions
37
- publish_all
38
40
  end
39
41
 
40
- def remove_consumer(consumer_id)
41
- $redis_jason.srem("jason:subscriptions:#{id}:consumers", consumer_id)
42
- $redis_jason.hdel("jason:consumers", consumer_id)
42
+ # Find and update subscriptions affected by a model changing foreign key
43
+ # 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
43
47
 
44
- if consumer_count == 0
45
- remove_subscriptions
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)
55
+ end
56
+
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)
46
61
  end
62
+
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])
66
+ end
67
+
68
+ # TODO changes to sub models - e.g. post -> comment -> user
47
69
  end
48
70
 
49
- def consumer_count
50
- $redis_jason.scard("jason:subscriptions:#{id}:consumers")
71
+ def self.remove_ids(model_name, ids)
72
+ ids.each do |instance_id|
73
+ for_instance(model_name, instance_id, false).each do |sub_id|
74
+ find_by_id(sub_id).remove_ids(model_name, [instance_id])
75
+ end
76
+ end
51
77
  end
52
78
 
53
- def channel
54
- "jason:#{id}"
79
+ # Add ID to any _all_ subscriptions
80
+ def self.add_id(model_name, id)
81
+
82
+ end
83
+
84
+ def self.all
85
+ $redis_jason.keys('jason:subscriptions:*')
86
+ end
87
+
88
+ 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])
97
+ end
98
+
99
+ def clear_id(model_name, id, parent_model_name)
100
+ remove_ids(model_name, [id])
55
101
  end
56
102
 
57
- def publish_all
58
- config.each do |model, model_config|
59
- klass = model.to_s.classify.constantize
60
- conditions = model_config['conditions'] || {}
61
- klass.where(conditions).find_each(&:cache_json)
62
- update(model)
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
63
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)
64
130
  end
65
131
 
66
- def add_subscriptions
67
- config.each do |model, value|
68
- $redis_jason.hset("jason:#{model.to_s.underscore}:subscriptions", id, value.to_json)
69
- update(model)
132
+ def refresh_ids(assoc_name = model, referrer_model_name = nil, referrer_ids)
133
+
134
+ end
135
+
136
+ # Add IDs that aren't present
137
+ def commit_ids(model_name, ids)
138
+ pp 'COMMIT'
139
+ pp model_name
140
+ pp ids
141
+ $redis_jason.sadd("jason:subscriptions:#{id}:ids:#{model_name}", ids)
142
+ ids.each do |instance_id|
143
+ $redis_jason.sadd("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
70
144
  end
71
145
  end
72
146
 
73
- def remove_subscriptions
74
- config.each do |model, _|
75
- $redis_jason.hdel("jason:#{model.to_s.underscore}:subscriptions", id)
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
+ $redis_jason.srem("jason:subscriptions:#{id}:ids:#{model_name}", (old_ids - ids))
153
+
154
+ (old_ids - ids).each do |instance_id|
155
+ $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
156
+ end
157
+
158
+ # Add
159
+ $redis_jason.sadd("jason:subscriptions:#{id}:ids:#{model_name}", (ids - old_ids))
160
+
161
+ (ids - old_ids).each do |instance_id|
162
+ $redis_jason.sadd("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
76
163
  end
77
164
  end
78
165
 
79
- def self.publish_all
80
- JASON_API_MODEL.each do |model, _v|
81
- klass = model.to_s.classify.constantize
82
- klass.publish_all(klass.all) if klass.respond_to?(:publish_all)
166
+ def remove_ids(model_name, ids)
167
+ $redis_jason.srem("jason:subscriptions:#{id}:ids:#{model_name}", ids)
168
+ ids.each do |instance_id|
169
+ $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
83
170
  end
84
171
  end
85
172
 
86
- def get(model)
87
- value = JSON.parse($redis_jason.get("#{channel}:#{model}:value") || '[]')
88
- idx = $redis_jason.get("#{channel}:#{model}:idx").to_i
173
+ # 'posts', [post#1, post#2,...]
174
+ def set_ids_for_sub_models(assoc_name, ids, enforce: false)
175
+ model_name = assoc_name.to_s.singularize
176
+ # Limitation: Same association can't appear twice
177
+ includes_tree = get_tree_for(assoc_name)
89
178
 
90
- {
91
- type: 'payload',
92
- md5Hash: id,
93
- model: model,
94
- value: value,
95
- idx: idx
96
- }
179
+ if includes_tree.is_a?(Hash)
180
+ includes_tree.each do |assoc_name, includes_tree|
181
+ set_ids(assoc_name, model_name, ids, enforce: enforce)
182
+ end
183
+ # [:likes, :user]
184
+ elsif includes_tree.is_a?(Array)
185
+ includes_tree.each do |assoc_name|
186
+ set_ids(assoc_name, model_name, ids, enforce: enforce)
187
+ end
188
+ elsif includes_tree.is_a?(String)
189
+ set_ids(includes_tree, model_name, ids, enforce: enforce)
190
+ end
97
191
  end
98
192
 
99
- def get_diff(old_value, value)
100
- JsonDiff.generate(old_value, value)
193
+ # assoc could be plural or not, so need to scan both.
194
+ def get_assoc_name(model_name, haystack = includes)
195
+ return model_name if model_name == model
196
+
197
+ if haystack.is_a?(Hash)
198
+ haystack.each do |assoc_name, includes_tree|
199
+ if model_name.pluralize == assoc_name.to_s.pluralize
200
+ return assoc_name
201
+ else
202
+ found_assoc = get_assoc_name(model_name, includes_tree)
203
+ return found_assoc if found_assoc
204
+ end
205
+ end
206
+ elsif haystack.is_a?(Array)
207
+ haystack.each do |assoc_name|
208
+ if model_name.pluralize == assoc_name.to_s.pluralize
209
+ return assoc_name
210
+ end
211
+ end
212
+ else
213
+ if model_name.pluralize == haystack.to_s.pluralize
214
+ return haystack
215
+ end
216
+ end
217
+
218
+ return nil
101
219
  end
102
220
 
103
- def deep_stringify(value)
104
- if value.is_a?(Hash)
105
- value.deep_stringify_keys
106
- elsif value.is_a?(Array)
107
- value.map { |x| x.deep_stringify_keys }
221
+ def get_tree_for(needle, assoc_name = nil, haystack = includes)
222
+ return includes if needle == model
223
+ return haystack if needle.to_s == assoc_name.to_s
224
+
225
+ if haystack.is_a?(Hash)
226
+ haystack.each do |assoc_name, includes_tree|
227
+ found_haystack = get_tree_for(needle, assoc_name, includes_tree)
228
+ return found_haystack if found_haystack
229
+ end
108
230
  end
231
+
232
+ return nil
109
233
  end
110
234
 
111
- def get_throttle
112
- if !$throttle_rate || !$throttle_timeout || Time.now.utc > $throttle_timeout
113
- $throttle_timeout = Time.now.utc + 5.seconds
114
- $throttle_rate = ($redis_jason.get('global_throttle_rate') || 0).to_i
235
+ def all_models(tree = includes)
236
+ sub_models = if tree.is_a?(Hash)
237
+ tree.map do |k,v|
238
+ [k, all_models(v)]
239
+ end
115
240
  else
116
- $throttle_rate
241
+ tree
117
242
  end
243
+
244
+ pp ([model] + [sub_models]).flatten.uniq.map(&:to_s).map(&:singularize)
245
+ ([model] + [sub_models]).flatten.uniq.map(&:to_s).map(&:singularize)
118
246
  end
119
247
 
120
- # Atomically update and return patch
121
- def update(model)
122
- start_time = Time.now.utc
123
- conditions = config[model]['conditions']
248
+ def clear_all_ids(assoc_name = model)
249
+ model_name = assoc_name.to_s.singularize
250
+ includes_tree = model_name == model ? includes : get_tree_for(assoc_name)
124
251
 
125
- value = $redis_jason.hgetall("jason:#{model}:cache")
126
- .values.map { |v| JSON.parse(v) }
127
- .select { |v| (conditions || {}).all? { |field, value| v[field] == value } }
128
- .sort_by { |v| v['id'] }
252
+ if model_name == model && conditions.blank?
253
+ $redis_jason.srem("jason:models:#{model_name}:all:subscriptions", id)
254
+ end
129
255
 
130
- # lfsa = last finished, started at
131
- # If another job that started after this one, finished before this one, skip sending this state update
132
- if Time.parse($redis_jason.get("jason:#{channel}:lfsa") || '1970-01-01 00:00:00 UTC') < start_time
133
- $redis_jason.set("jason:#{channel}:lfsa", start_time)
134
- else
135
- return
256
+ ids = $redis_jason.smembers("jason:subscriptions:#{id}:ids:#{model_name}")
257
+ ids.each do |instance_id|
258
+ $redis_jason.srem("jason:models:#{model_name}:#{instance_id}:subscriptions", id)
259
+ end
260
+ $redis_jason.del("jason:subscriptions:#{id}:ids:#{model_name}")
261
+
262
+ # Recursively clear IDs
263
+ # { comments: [:like] }
264
+ if includes_tree.is_a?(Hash)
265
+ includes_tree.each do |assoc_name, includes_tree|
266
+ clear_all_ids(assoc_name)
267
+ end
268
+ # [:likes, :user]
269
+ elsif includes_tree.is_a?(Array)
270
+ includes_tree.each do |assoc_name|
271
+ clear_all_ids(assoc_name)
272
+ end
273
+ elsif includes_tree.is_a?(String)
274
+ clear_all_ids(includes_tree)
136
275
  end
276
+ end
137
277
 
138
- value = deep_stringify(value)
278
+ def ids(model_name = model)
279
+ $redis_jason.smembers("jason:subscriptions:#{id}:ids:#{model_name}")
280
+ end
139
281
 
140
- # If value has changed, return old value and new idx. Otherwise do nothing.
141
- cmd = <<~LUA
142
- local old_val=redis.call('get', ARGV[1] .. ':value')
143
- if old_val ~= ARGV[2] then
144
- redis.call('set', ARGV[1] .. ':value', ARGV[2])
145
- local new_idx = redis.call('incr', ARGV[1] .. ':idx')
146
- return { new_idx, old_val }
282
+ def model
283
+ @config['model']
284
+ end
285
+
286
+ def model_klass(model_name)
287
+ model_name.to_s.classify.constantize
288
+ end
289
+
290
+ def conditions
291
+ @config['conditions']
292
+ end
293
+
294
+ def includes
295
+ @config['includes']
296
+ end
297
+
298
+ def configure(raw_config)
299
+ set_config(raw_config)
300
+ $redis_jason.hmset("jason:subscriptions:#{id}", *config.map { |k,v| [k, v.to_json] }.flatten)
301
+ end
302
+
303
+ def destroy
304
+ raise
305
+ end
306
+
307
+ def add_consumer(consumer_id)
308
+ before_consumer_count = consumer_count
309
+ $redis_jason.sadd("jason:subscriptions:#{id}:consumers", consumer_id)
310
+ $redis_jason.hset("jason:consumers", consumer_id, Time.now.utc)
311
+
312
+ if before_consumer_count == 0
313
+ set_ids
314
+ end
315
+ end
316
+
317
+ def remove_consumer(consumer_id)
318
+ $redis_jason.srem("jason:subscriptions:#{id}:consumers", consumer_id)
319
+ $redis_jason.hdel("jason:consumers", consumer_id)
320
+
321
+ if consumer_count == 0
322
+ clear_all_ids
323
+ end
324
+ end
325
+
326
+ def consumer_count
327
+ $redis_jason.scard("jason:subscriptions:#{id}:consumers")
328
+ end
329
+
330
+ def channel
331
+ "jason:#{id}"
332
+ end
333
+
334
+ def get
335
+ all_models.map { |model_name| get_for_model(model_name) }
336
+ end
337
+
338
+ def get_for_model(model_name)
339
+ if $redis_jason.sismember("jason:models:#{model_name}:all:subscriptions", id)
340
+ instance_jsons_hash, idx = $redis_jason.multi do |r|
341
+ r.hgetall("jason:cache:#{model_name}")
342
+ r.get("jason:subscription:#{id}:#{model_name}:idx")
147
343
  end
148
- LUA
344
+ instance_jsons = instance_jsons_hash.values
345
+ else
346
+ instance_jsons, idx = Jason::LuaGenerator.new.get_payload(model_name, id)
347
+ end
149
348
 
150
- result = $redis_jason.eval cmd, [], ["#{channel}:#{model}", value.to_json]
151
- return if result.blank?
349
+ return if instance_jsons.blank?
152
350
 
153
- idx = result[0]
154
- old_value = JSON.parse(result[1] || '[]')
155
- diff = get_diff(old_value, value)
351
+ payload = instance_jsons.map do |instance_json|
352
+ instance_json ? JSON.parse(instance_json) : {}
353
+ end
354
+
355
+ {
356
+ type: 'payload',
357
+ model: model_name,
358
+ payload: payload,
359
+ md5Hash: id,
360
+ idx: idx.to_i
361
+ }
362
+ end
156
363
 
157
- end_time = Time.now.utc
364
+ def update(model_name, instance_id, payload, gidx)
365
+ idx = Jason::LuaGenerator.new.get_subscription(model_name, instance_id, id, gidx)
366
+ return if idx.blank?
158
367
 
159
368
  payload = {
160
- model: model,
369
+ id: instance_id,
370
+ model: model_name,
371
+ payload: payload,
372
+ md5Hash: id,
373
+ idx: idx.to_i
374
+ }
375
+
376
+ ActionCable.server.broadcast(channel, payload)
377
+ end
378
+
379
+ def destroy(model_name, instance_id)
380
+ idx = $redis_jason.incr("jason:subscription:#{id}:#{model_name}idx")
381
+
382
+ payload = {
383
+ id: instance_id,
384
+ model: model_name,
385
+ destroy: true,
161
386
  md5Hash: id,
162
- diff: diff,
163
- idx: idx.to_i,
164
- latency: ((end_time - start_time)*1000).round
387
+ idx: idx.to_i
165
388
  }
166
389
 
167
- ActionCable.server.broadcast("jason:#{id}", payload)
390
+ ActionCable.server.broadcast(channel, payload)
168
391
  end
169
392
  end