jason-rails 0.4.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.ruby-version +1 -0
  4. data/Gemfile.lock +152 -2
  5. data/README.md +117 -5
  6. data/app/controllers/jason/api/pusher_controller.rb +15 -0
  7. data/app/controllers/jason/api_controller.rb +44 -2
  8. data/client/lib/JasonContext.d.ts +6 -1
  9. data/client/lib/JasonContext.js +4 -1
  10. data/client/lib/JasonProvider.d.ts +2 -2
  11. data/client/lib/JasonProvider.js +5 -124
  12. data/client/lib/createJasonReducers.js +48 -3
  13. data/client/lib/createOptDis.js +0 -2
  14. data/client/lib/createPayloadHandler.d.ts +9 -1
  15. data/client/lib/createPayloadHandler.js +47 -55
  16. data/client/lib/createServerActionQueue.d.ts +10 -0
  17. data/client/lib/createServerActionQueue.js +48 -0
  18. data/client/lib/createServerActionQueue.test.d.ts +1 -0
  19. data/client/lib/createServerActionQueue.test.js +37 -0
  20. data/client/lib/createTransportAdapter.d.ts +5 -0
  21. data/client/lib/createTransportAdapter.js +20 -0
  22. data/client/lib/index.d.ts +5 -2
  23. data/client/lib/index.js +3 -1
  24. data/client/lib/makeEager.js +2 -2
  25. data/client/lib/pruneIdsMiddleware.d.ts +2 -0
  26. data/client/lib/pruneIdsMiddleware.js +24 -0
  27. data/client/lib/restClient.d.ts +2 -0
  28. data/client/lib/restClient.js +17 -0
  29. data/client/lib/transportAdapters/actionCableAdapter.d.ts +5 -0
  30. data/client/lib/transportAdapters/actionCableAdapter.js +35 -0
  31. data/client/lib/transportAdapters/pusherAdapter.d.ts +5 -0
  32. data/client/lib/transportAdapters/pusherAdapter.js +68 -0
  33. data/client/lib/useJason.d.ts +5 -0
  34. data/client/lib/useJason.js +94 -0
  35. data/client/lib/useJason.test.d.ts +1 -0
  36. data/client/lib/useJason.test.js +85 -0
  37. data/client/lib/useSub.d.ts +1 -1
  38. data/client/lib/useSub.js +6 -3
  39. data/client/package.json +5 -3
  40. data/client/src/JasonContext.ts +4 -1
  41. data/client/src/JasonProvider.tsx +5 -123
  42. data/client/src/createJasonReducers.ts +56 -3
  43. data/client/src/createOptDis.ts +0 -2
  44. data/client/src/createPayloadHandler.ts +53 -64
  45. data/client/src/createServerActionQueue.test.ts +42 -0
  46. data/client/src/createServerActionQueue.ts +47 -0
  47. data/client/src/createTransportAdapter.ts +13 -0
  48. data/client/src/index.ts +3 -1
  49. data/client/src/makeEager.ts +2 -2
  50. data/client/src/pruneIdsMiddleware.ts +24 -0
  51. data/client/src/restClient.ts +14 -0
  52. data/client/src/transportAdapters/actionCableAdapter.ts +38 -0
  53. data/client/src/transportAdapters/pusherAdapter.ts +72 -0
  54. data/client/src/useJason.test.ts +87 -0
  55. data/client/src/useJason.ts +110 -0
  56. data/client/src/useSub.ts +6 -3
  57. data/client/yarn.lock +71 -3
  58. data/config/routes.rb +5 -1
  59. data/jason-rails.gemspec +4 -0
  60. data/lib/jason.rb +61 -1
  61. data/lib/jason/api_model.rb +2 -12
  62. data/lib/jason/broadcaster.rb +19 -0
  63. data/lib/jason/channel.rb +50 -21
  64. data/lib/jason/graph_helper.rb +165 -0
  65. data/lib/jason/includes_helper.rb +108 -0
  66. data/lib/jason/lua_generator.rb +71 -0
  67. data/lib/jason/publisher.rb +82 -37
  68. data/lib/jason/publisher_old.rb +112 -0
  69. data/lib/jason/subscription.rb +349 -97
  70. data/lib/jason/subscription_old.rb +171 -0
  71. data/lib/jason/version.rb +1 -1
  72. metadata +80 -3
@@ -0,0 +1,171 @@
1
+ class Jason::SubscriptionOld
2
+ attr_accessor :id, :config
3
+
4
+ def initialize(id: nil, config: nil)
5
+ if id
6
+ @id = id
7
+ raw_config = $redis_jason.hgetall("jason:subscriptions:#{id}").map { |k,v| [k, JSON.parse(v)] }.to_h
8
+ set_config(raw_config)
9
+ else
10
+ @id = Digest::MD5.hexdigest(config.to_json)
11
+ configure(config)
12
+ end
13
+ end
14
+
15
+ def set_config(raw_config)
16
+ @config = raw_config.with_indifferent_access.map { |k,v| [k.underscore.to_s, v] }.to_h
17
+ end
18
+
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)
22
+ end
23
+
24
+ def destroy
25
+ config.each do |model, value|
26
+ $redis_jason.srem("jason:#{model.to_s.underscore}:subscriptions", id)
27
+ end
28
+ $redis_jason.del("jason:subscriptions:#{id}")
29
+ end
30
+
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)
35
+
36
+ add_subscriptions
37
+ publish_all
38
+ end
39
+
40
+ def remove_consumer(consumer_id)
41
+ $redis_jason.srem("jason:subscriptions:#{id}:consumers", consumer_id)
42
+ $redis_jason.hdel("jason:consumers", consumer_id)
43
+
44
+ if consumer_count == 0
45
+ remove_subscriptions
46
+ end
47
+ end
48
+
49
+ def consumer_count
50
+ $redis_jason.scard("jason:subscriptions:#{id}:consumers")
51
+ end
52
+
53
+ def channel
54
+ "jason:#{id}"
55
+ end
56
+
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)
63
+ end
64
+ end
65
+
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)
70
+ end
71
+ end
72
+
73
+ def remove_subscriptions
74
+ config.each do |model, _|
75
+ $redis_jason.hdel("jason:#{model.to_s.underscore}:subscriptions", id)
76
+ end
77
+ end
78
+
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)
83
+ end
84
+ end
85
+
86
+ def get(model_name)
87
+ LuaGenerator.new.index_hash_by_set("jason:cache:#{model_name}", "")
88
+
89
+ value = JSON.parse($redis_jason.get("#{channel}:#{model}:value") || '[]')
90
+ idx = $redis_jason.get("#{channel}:#{model}:idx").to_i
91
+
92
+ {
93
+ type: 'payload',
94
+ md5Hash: id,
95
+ model: model,
96
+ value: value,
97
+ idx: idx
98
+ }
99
+ end
100
+
101
+ def get_diff(old_value, value)
102
+ JsonDiff.generate(old_value, value)
103
+ end
104
+
105
+ def deep_stringify(value)
106
+ if value.is_a?(Hash)
107
+ value.deep_stringify_keys
108
+ elsif value.is_a?(Array)
109
+ value.map { |x| x.deep_stringify_keys }
110
+ end
111
+ end
112
+
113
+ def get_throttle
114
+ if !$throttle_rate || !$throttle_timeout || Time.now.utc > $throttle_timeout
115
+ $throttle_timeout = Time.now.utc + 5.seconds
116
+ $throttle_rate = ($redis_jason.get('global_throttle_rate') || 0).to_i
117
+ else
118
+ $throttle_rate
119
+ end
120
+ end
121
+
122
+ # Atomically update and return patch
123
+ def update(model)
124
+ start_time = Time.now.utc
125
+ conditions = config[model]['conditions']
126
+
127
+ value = $redis_jason.hgetall("jason:#{model}:cache")
128
+ .values.map { |v| JSON.parse(v) }
129
+ .select { |v| (conditions || {}).all? { |field, value| v[field] == value } }
130
+ .sort_by { |v| v['id'] }
131
+
132
+ # lfsa = last finished, started at
133
+ # If another job that started after this one, finished before this one, skip sending this state update
134
+ if Time.parse($redis_jason.get("jason:#{channel}:lfsa") || '1970-01-01 00:00:00 UTC') < start_time
135
+ $redis_jason.set("jason:#{channel}:lfsa", start_time)
136
+ else
137
+ return
138
+ end
139
+
140
+ value = deep_stringify(value)
141
+
142
+ # If value has changed, return old value and new idx. Otherwise do nothing.
143
+ cmd = <<~LUA
144
+ local old_val=redis.call('get', ARGV[1] .. ':value')
145
+ if old_val ~= ARGV[2] then
146
+ redis.call('set', ARGV[1] .. ':value', ARGV[2])
147
+ local new_idx = redis.call('incr', ARGV[1] .. ':idx')
148
+ return { new_idx, old_val }
149
+ end
150
+ LUA
151
+
152
+ result = $redis_jason.eval cmd, [], ["#{channel}:#{model}", value.to_json]
153
+ return if result.blank?
154
+
155
+ idx = result[0]
156
+ old_value = JSON.parse(result[1] || '[]')
157
+ diff = get_diff(old_value, value)
158
+
159
+ end_time = Time.now.utc
160
+
161
+ payload = {
162
+ model: model,
163
+ md5Hash: id,
164
+ diff: diff,
165
+ idx: idx.to_i,
166
+ latency: ((end_time - start_time)*1000).round
167
+ }
168
+
169
+ ActionCable.server.broadcast("jason:#{id}", payload)
170
+ end
171
+ end
data/lib/jason/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jason
2
- VERSION = "0.4.1"
2
+ VERSION = "0.6.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jason-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Rees
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -66,6 +66,48 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
69
111
  description:
70
112
  email:
71
113
  - jarees@gmail.com
@@ -75,6 +117,7 @@ extra_rdoc_files: []
75
117
  files:
76
118
  - ".gitignore"
77
119
  - ".rspec"
120
+ - ".ruby-version"
78
121
  - ".travis.yml"
79
122
  - CODE_OF_CONDUCT.md
80
123
  - Gemfile
@@ -82,6 +125,7 @@ files:
82
125
  - LICENSE.txt
83
126
  - README.md
84
127
  - Rakefile
128
+ - app/controllers/jason/api/pusher_controller.rb
85
129
  - app/controllers/jason/api_controller.rb
86
130
  - bin/console
87
131
  - bin/setup
@@ -100,6 +144,12 @@ files:
100
144
  - client/lib/createOptDis.js
101
145
  - client/lib/createPayloadHandler.d.ts
102
146
  - client/lib/createPayloadHandler.js
147
+ - client/lib/createServerActionQueue.d.ts
148
+ - client/lib/createServerActionQueue.js
149
+ - client/lib/createServerActionQueue.test.d.ts
150
+ - client/lib/createServerActionQueue.test.js
151
+ - client/lib/createTransportAdapter.d.ts
152
+ - client/lib/createTransportAdapter.js
103
153
  - client/lib/deepCamelizeKeys.d.ts
104
154
  - client/lib/deepCamelizeKeys.js
105
155
  - client/lib/deepCamelizeKeys.test.d.ts
@@ -108,8 +158,20 @@ files:
108
158
  - client/lib/index.js
109
159
  - client/lib/makeEager.d.ts
110
160
  - client/lib/makeEager.js
161
+ - client/lib/pruneIdsMiddleware.d.ts
162
+ - client/lib/pruneIdsMiddleware.js
163
+ - client/lib/restClient.d.ts
164
+ - client/lib/restClient.js
165
+ - client/lib/transportAdapters/actionCableAdapter.d.ts
166
+ - client/lib/transportAdapters/actionCableAdapter.js
167
+ - client/lib/transportAdapters/pusherAdapter.d.ts
168
+ - client/lib/transportAdapters/pusherAdapter.js
111
169
  - client/lib/useAct.d.ts
112
170
  - client/lib/useAct.js
171
+ - client/lib/useJason.d.ts
172
+ - client/lib/useJason.js
173
+ - client/lib/useJason.test.d.ts
174
+ - client/lib/useJason.test.js
113
175
  - client/lib/useSub.d.ts
114
176
  - client/lib/useSub.js
115
177
  - client/package.json
@@ -120,11 +182,20 @@ files:
120
182
  - client/src/createJasonReducers.ts
121
183
  - client/src/createOptDis.ts
122
184
  - client/src/createPayloadHandler.ts
185
+ - client/src/createServerActionQueue.test.ts
186
+ - client/src/createServerActionQueue.ts
187
+ - client/src/createTransportAdapter.ts
123
188
  - client/src/deepCamelizeKeys.test.ts
124
189
  - client/src/deepCamelizeKeys.ts
125
190
  - client/src/index.ts
126
191
  - client/src/makeEager.ts
192
+ - client/src/pruneIdsMiddleware.ts
193
+ - client/src/restClient.ts
194
+ - client/src/transportAdapters/actionCableAdapter.ts
195
+ - client/src/transportAdapters/pusherAdapter.ts
127
196
  - client/src/useAct.ts
197
+ - client/src/useJason.test.ts
198
+ - client/src/useJason.ts
128
199
  - client/src/useSub.ts
129
200
  - client/tsconfig.json
130
201
  - client/yarn.lock
@@ -132,10 +203,16 @@ files:
132
203
  - jason-rails.gemspec
133
204
  - lib/jason.rb
134
205
  - lib/jason/api_model.rb
206
+ - lib/jason/broadcaster.rb
135
207
  - lib/jason/channel.rb
136
208
  - lib/jason/engine.rb
209
+ - lib/jason/graph_helper.rb
210
+ - lib/jason/includes_helper.rb
211
+ - lib/jason/lua_generator.rb
137
212
  - lib/jason/publisher.rb
213
+ - lib/jason/publisher_old.rb
138
214
  - lib/jason/subscription.rb
215
+ - lib/jason/subscription_old.rb
139
216
  - lib/jason/version.rb
140
217
  homepage: https://github.com/jamesr2323/jason
141
218
  licenses:
@@ -159,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
236
  - !ruby/object:Gem::Version
160
237
  version: '0'
161
238
  requirements: []
162
- rubygems_version: 3.0.8
239
+ rubygems_version: 3.1.4
163
240
  signing_key:
164
241
  specification_version: 4
165
242
  summary: Reactive user interfaces with minimal boilerplate, using Rails + Redux