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,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
@@ -1,3 +1,3 @@
1
1
  module Jason
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
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.5.0
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-01-27 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
@@ -100,6 +143,10 @@ files:
100
143
  - client/lib/createOptDis.js
101
144
  - client/lib/createPayloadHandler.d.ts
102
145
  - client/lib/createPayloadHandler.js
146
+ - client/lib/createServerActionQueue.d.ts
147
+ - client/lib/createServerActionQueue.js
148
+ - client/lib/createServerActionQueue.test.d.ts
149
+ - client/lib/createServerActionQueue.test.js
103
150
  - client/lib/deepCamelizeKeys.d.ts
104
151
  - client/lib/deepCamelizeKeys.js
105
152
  - client/lib/deepCamelizeKeys.test.d.ts
@@ -108,8 +155,16 @@ files:
108
155
  - client/lib/index.js
109
156
  - client/lib/makeEager.d.ts
110
157
  - client/lib/makeEager.js
158
+ - client/lib/pruneIdsMiddleware.d.ts
159
+ - client/lib/pruneIdsMiddleware.js
160
+ - client/lib/restClient.d.ts
161
+ - client/lib/restClient.js
111
162
  - client/lib/useAct.d.ts
112
163
  - client/lib/useAct.js
164
+ - client/lib/useJason.d.ts
165
+ - client/lib/useJason.js
166
+ - client/lib/useJason.test.d.ts
167
+ - client/lib/useJason.test.js
113
168
  - client/lib/useSub.d.ts
114
169
  - client/lib/useSub.js
115
170
  - client/package.json
@@ -120,11 +175,17 @@ files:
120
175
  - client/src/createJasonReducers.ts
121
176
  - client/src/createOptDis.ts
122
177
  - client/src/createPayloadHandler.ts
178
+ - client/src/createServerActionQueue.test.ts
179
+ - client/src/createServerActionQueue.ts
123
180
  - client/src/deepCamelizeKeys.test.ts
124
181
  - client/src/deepCamelizeKeys.ts
125
182
  - client/src/index.ts
126
183
  - client/src/makeEager.ts
184
+ - client/src/pruneIdsMiddleware.ts
185
+ - client/src/restClient.ts
127
186
  - client/src/useAct.ts
187
+ - client/src/useJason.test.ts
188
+ - client/src/useJason.ts
128
189
  - client/src/useSub.ts
129
190
  - client/tsconfig.json
130
191
  - client/yarn.lock
@@ -134,8 +195,11 @@ files:
134
195
  - lib/jason/api_model.rb
135
196
  - lib/jason/channel.rb
136
197
  - lib/jason/engine.rb
198
+ - lib/jason/lua_generator.rb
137
199
  - lib/jason/publisher.rb
200
+ - lib/jason/publisher_old.rb
138
201
  - lib/jason/subscription.rb
202
+ - lib/jason/subscription_old.rb
139
203
  - lib/jason/version.rb
140
204
  homepage: https://github.com/jamesr2323/jason
141
205
  licenses:
@@ -159,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
223
  - !ruby/object:Gem::Version
160
224
  version: '0'
161
225
  requirements: []
162
- rubygems_version: 3.0.8
226
+ rubygems_version: 3.1.4
163
227
  signing_key:
164
228
  specification_version: 4
165
229
  summary: Reactive user interfaces with minimal boilerplate, using Rails + Redux