jason-rails 0.4.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) 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/JasonProvider.d.ts +2 -2
  10. data/client/lib/JasonProvider.js +5 -124
  11. data/client/lib/createJasonReducers.js +48 -3
  12. data/client/lib/createOptDis.js +0 -2
  13. data/client/lib/createPayloadHandler.d.ts +9 -1
  14. data/client/lib/createPayloadHandler.js +47 -55
  15. data/client/lib/createServerActionQueue.d.ts +10 -0
  16. data/client/lib/createServerActionQueue.js +48 -0
  17. data/client/lib/createServerActionQueue.test.d.ts +1 -0
  18. data/client/lib/createServerActionQueue.test.js +37 -0
  19. data/client/lib/createTransportAdapter.d.ts +5 -0
  20. data/client/lib/createTransportAdapter.js +20 -0
  21. data/client/lib/index.d.ts +3 -2
  22. data/client/lib/pruneIdsMiddleware.d.ts +2 -0
  23. data/client/lib/pruneIdsMiddleware.js +24 -0
  24. data/client/lib/restClient.d.ts +2 -0
  25. data/client/lib/restClient.js +17 -0
  26. data/client/lib/transportAdapters/actionCableAdapter.d.ts +5 -0
  27. data/client/lib/transportAdapters/actionCableAdapter.js +35 -0
  28. data/client/lib/transportAdapters/pusherAdapter.d.ts +5 -0
  29. data/client/lib/transportAdapters/pusherAdapter.js +68 -0
  30. data/client/lib/useJason.d.ts +5 -0
  31. data/client/lib/useJason.js +94 -0
  32. data/client/lib/useJason.test.d.ts +1 -0
  33. data/client/lib/useJason.test.js +85 -0
  34. data/client/lib/useSub.d.ts +1 -1
  35. data/client/lib/useSub.js +6 -3
  36. data/client/package.json +5 -3
  37. data/client/src/JasonProvider.tsx +5 -123
  38. data/client/src/createJasonReducers.ts +56 -3
  39. data/client/src/createOptDis.ts +0 -2
  40. data/client/src/createPayloadHandler.ts +53 -64
  41. data/client/src/createServerActionQueue.test.ts +42 -0
  42. data/client/src/createServerActionQueue.ts +47 -0
  43. data/client/src/createTransportAdapter.ts +13 -0
  44. data/client/src/pruneIdsMiddleware.ts +24 -0
  45. data/client/src/restClient.ts +14 -0
  46. data/client/src/transportAdapters/actionCableAdapter.ts +38 -0
  47. data/client/src/transportAdapters/pusherAdapter.ts +72 -0
  48. data/client/src/useJason.test.ts +87 -0
  49. data/client/src/useJason.ts +110 -0
  50. data/client/src/useSub.ts +6 -3
  51. data/client/yarn.lock +71 -3
  52. data/config/routes.rb +5 -1
  53. data/jason-rails.gemspec +4 -0
  54. data/lib/jason.rb +61 -1
  55. data/lib/jason/api_model.rb +2 -12
  56. data/lib/jason/broadcaster.rb +19 -0
  57. data/lib/jason/channel.rb +50 -21
  58. data/lib/jason/graph_helper.rb +165 -0
  59. data/lib/jason/includes_helper.rb +108 -0
  60. data/lib/jason/lua_generator.rb +71 -0
  61. data/lib/jason/publisher.rb +82 -37
  62. data/lib/jason/publisher_old.rb +112 -0
  63. data/lib/jason/subscription.rb +349 -97
  64. data/lib/jason/subscription_old.rb +171 -0
  65. data/lib/jason/version.rb +1 -1
  66. metadata +80 -11
  67. data/app/assets/config/jason_engine_manifest.js +0 -1
  68. data/app/assets/images/jason/engine/.keep +0 -0
  69. data/app/assets/stylesheets/jason/engine/application.css +0 -15
  70. data/app/helpers/jason/engine/application_helper.rb +0 -6
  71. data/app/jobs/jason/engine/application_job.rb +0 -6
  72. data/app/mailers/jason/engine/application_mailer.rb +0 -8
  73. data/app/models/jason/engine/application_record.rb +0 -7
  74. data/app/views/layouts/jason/engine/application.html.erb +0 -15
@@ -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.0"
2
+ VERSION = "0.6.1"
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.0
4
+ version: 0.6.1
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,15 +125,8 @@ files:
82
125
  - LICENSE.txt
83
126
  - README.md
84
127
  - Rakefile
85
- - app/assets/config/jason_engine_manifest.js
86
- - app/assets/images/jason/engine/.keep
87
- - app/assets/stylesheets/jason/engine/application.css
128
+ - app/controllers/jason/api/pusher_controller.rb
88
129
  - app/controllers/jason/api_controller.rb
89
- - app/helpers/jason/engine/application_helper.rb
90
- - app/jobs/jason/engine/application_job.rb
91
- - app/mailers/jason/engine/application_mailer.rb
92
- - app/models/jason/engine/application_record.rb
93
- - app/views/layouts/jason/engine/application.html.erb
94
130
  - bin/console
95
131
  - bin/setup
96
132
  - client/babel.config.js
@@ -108,6 +144,12 @@ files:
108
144
  - client/lib/createOptDis.js
109
145
  - client/lib/createPayloadHandler.d.ts
110
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
111
153
  - client/lib/deepCamelizeKeys.d.ts
112
154
  - client/lib/deepCamelizeKeys.js
113
155
  - client/lib/deepCamelizeKeys.test.d.ts
@@ -116,8 +158,20 @@ files:
116
158
  - client/lib/index.js
117
159
  - client/lib/makeEager.d.ts
118
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
119
169
  - client/lib/useAct.d.ts
120
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
121
175
  - client/lib/useSub.d.ts
122
176
  - client/lib/useSub.js
123
177
  - client/package.json
@@ -128,11 +182,20 @@ files:
128
182
  - client/src/createJasonReducers.ts
129
183
  - client/src/createOptDis.ts
130
184
  - client/src/createPayloadHandler.ts
185
+ - client/src/createServerActionQueue.test.ts
186
+ - client/src/createServerActionQueue.ts
187
+ - client/src/createTransportAdapter.ts
131
188
  - client/src/deepCamelizeKeys.test.ts
132
189
  - client/src/deepCamelizeKeys.ts
133
190
  - client/src/index.ts
134
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
135
196
  - client/src/useAct.ts
197
+ - client/src/useJason.test.ts
198
+ - client/src/useJason.ts
136
199
  - client/src/useSub.ts
137
200
  - client/tsconfig.json
138
201
  - client/yarn.lock
@@ -140,10 +203,16 @@ files:
140
203
  - jason-rails.gemspec
141
204
  - lib/jason.rb
142
205
  - lib/jason/api_model.rb
206
+ - lib/jason/broadcaster.rb
143
207
  - lib/jason/channel.rb
144
208
  - lib/jason/engine.rb
209
+ - lib/jason/graph_helper.rb
210
+ - lib/jason/includes_helper.rb
211
+ - lib/jason/lua_generator.rb
145
212
  - lib/jason/publisher.rb
213
+ - lib/jason/publisher_old.rb
146
214
  - lib/jason/subscription.rb
215
+ - lib/jason/subscription_old.rb
147
216
  - lib/jason/version.rb
148
217
  homepage: https://github.com/jamesr2323/jason
149
218
  licenses:
@@ -167,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
236
  - !ruby/object:Gem::Version
168
237
  version: '0'
169
238
  requirements: []
170
- rubygems_version: 3.0.8
239
+ rubygems_version: 3.1.4
171
240
  signing_key:
172
241
  specification_version: 4
173
242
  summary: Reactive user interfaces with minimal boilerplate, using Rails + Redux
@@ -1 +0,0 @@
1
- //= link_directory ../stylesheets/jason/engine .css
File without changes
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,6 +0,0 @@
1
- module Jason
2
- module Engine
3
- module ApplicationHelper
4
- end
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- module Jason
2
- module Engine
3
- class ApplicationJob < ActiveJob::Base
4
- end
5
- end
6
- end
@@ -1,8 +0,0 @@
1
- module Jason
2
- module Engine
3
- class ApplicationMailer < ActionMailer::Base
4
- default from: 'from@example.com'
5
- layout 'mailer'
6
- end
7
- end
8
- end
@@ -1,7 +0,0 @@
1
- module Jason
2
- module Engine
3
- class ApplicationRecord < ActiveRecord::Base
4
- self.abstract_class = true
5
- end
6
- end
7
- end
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Jason engine</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "jason/engine/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>