jason-rails 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +34 -0
  3. data/README.md +6 -9
  4. data/app/assets/config/jason_engine_manifest.js +1 -0
  5. data/app/assets/images/jason/engine/.keep +0 -0
  6. data/app/assets/stylesheets/jason/engine/application.css +15 -0
  7. data/app/controllers/jason/api_controller.rb +36 -0
  8. data/app/helpers/jason/engine/application_helper.rb +6 -0
  9. data/app/jobs/jason/engine/application_job.rb +6 -0
  10. data/app/mailers/jason/engine/application_mailer.rb +8 -0
  11. data/app/models/jason/engine/application_record.rb +7 -0
  12. data/app/views/layouts/jason/engine/application.html.erb +15 -0
  13. data/client/babel.config.js +13 -0
  14. data/client/lib/JasonProvider.d.ts +5 -4
  15. data/client/lib/JasonProvider.js +30 -3
  16. data/client/lib/actionFactory.js +1 -1
  17. data/client/lib/createActions.d.ts +1 -1
  18. data/client/lib/createActions.js +2 -27
  19. data/client/lib/createJasonReducers.js +1 -0
  20. data/client/lib/createOptDis.d.ts +1 -0
  21. data/client/lib/createOptDis.js +45 -0
  22. data/client/lib/createPayloadHandler.d.ts +1 -1
  23. data/client/lib/createPayloadHandler.js +23 -6
  24. data/client/lib/deepCamelizeKeys.d.ts +1 -0
  25. data/client/lib/deepCamelizeKeys.js +23 -0
  26. data/client/lib/deepCamelizeKeys.test.d.ts +1 -0
  27. data/client/lib/deepCamelizeKeys.test.js +106 -0
  28. data/client/lib/index.d.ts +4 -4
  29. data/client/package.json +17 -4
  30. data/client/src/JasonProvider.tsx +33 -5
  31. data/client/src/actionFactory.ts +1 -1
  32. data/client/src/createActions.ts +2 -33
  33. data/client/src/createJasonReducers.ts +1 -0
  34. data/client/src/createOptDis.ts +47 -0
  35. data/client/src/createPayloadHandler.ts +26 -4
  36. data/client/src/deepCamelizeKeys.test.ts +113 -0
  37. data/client/src/deepCamelizeKeys.ts +17 -0
  38. data/client/yarn.lock +4539 -81
  39. data/config/routes.rb +4 -0
  40. data/jason-rails.gemspec +5 -0
  41. data/lib/jason.rb +7 -1
  42. data/lib/jason/api_model.rb +16 -0
  43. data/lib/jason/channel.rb +2 -2
  44. data/lib/jason/engine.rb +5 -0
  45. data/lib/jason/publisher.rb +38 -6
  46. data/lib/jason/subscription.rb +21 -24
  47. data/lib/jason/version.rb +1 -1
  48. metadata +81 -3
@@ -0,0 +1,4 @@
1
+ Jason::Engine.routes.draw do
2
+ get '/api/schema', to: 'api#schema'
3
+ post '/api/action', to: 'api#action'
4
+ end
@@ -22,4 +22,9 @@ Gem::Specification.new do |spec|
22
22
  end
23
23
  spec.executables = []
24
24
  spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency "rails", ">= 5"
27
+ spec.add_dependency "connection_pool", ">= 2.2.3"
28
+ spec.add_dependency "redis", ">= 4"
29
+ spec.add_dependency "jsondiff"
25
30
  end
@@ -1,10 +1,16 @@
1
+ require 'connection_pool'
2
+ require 'redis'
3
+ require 'jsondiff'
4
+
1
5
  require "jason/version"
2
6
  require 'jason/api_model'
3
7
  require 'jason/channel'
4
8
  require 'jason/publisher'
5
9
  require 'jason/subscription'
10
+ require 'jason/engine'
6
11
 
7
12
  module Jason
8
13
  class Error < StandardError; end
9
- # Your code goes here...
14
+
15
+ $redis_jason = ::ConnectionPool::Wrapper.new(size: 5, timeout: 3) { ::Redis.new(url: ENV['REDIS_URL']) }
10
16
  end
@@ -15,6 +15,10 @@ class Jason::ApiModel
15
15
  model.allowed_params || []
16
16
  end
17
17
 
18
+ def allowed_object_params
19
+ model.allowed_object_params || []
20
+ end
21
+
18
22
  def include_models
19
23
  model.include_models || []
20
24
  end
@@ -35,6 +39,18 @@ class Jason::ApiModel
35
39
  model.scope
36
40
  end
37
41
 
42
+ def permit(params)
43
+ pp self
44
+ pp params
45
+ params = params.require(:payload).permit(allowed_params).tap do |allowed|
46
+ pp "ALLOWED"
47
+ pp allowed
48
+ allowed_object_params.each do |key|
49
+ allowed[key] = params[:payload][key].to_unsafe_h if params[:payload][key]
50
+ end
51
+ end
52
+ end
53
+
38
54
  def as_json_config
39
55
  include_configs = include_models.map do |assoc|
40
56
  reflection = name.classify.constantize.reflect_on_association(assoc.to_sym)
@@ -24,8 +24,8 @@ class Jason::Channel < ActionCable::Channel::Base
24
24
  # stream_from s.channel
25
25
  # end
26
26
  elsif (data = message['getPayload'])
27
- config = data.config
28
- model = data.model
27
+ config = data['config']
28
+ model = data['model']
29
29
  Jason::Subscription.new(config: config).get(model.to_s.underscore)
30
30
  end
31
31
  rescue => e
@@ -0,0 +1,5 @@
1
+ module Jason
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Jason
4
+ end
5
+ end
@@ -7,17 +7,16 @@ module Jason::Publisher
7
7
 
8
8
  if self.persisted? && (scope.blank? || self.class.unscoped.send(scope).exists?(self.id))
9
9
  payload = self.reload.as_json(as_json_config)
10
- $redis.hset("jason:#{self.class.name.underscore}:cache", self.id, payload.to_json)
10
+ $redis_jason.hset("jason:#{self.class.name.underscore}:cache", self.id, payload.to_json)
11
11
  else
12
- $redis.hdel("jason:#{self.class.name.underscore}:cache", self.id)
12
+ $redis_jason.hdel("jason:#{self.class.name.underscore}:cache", self.id)
13
13
  end
14
14
  end
15
15
 
16
16
  def publish_json
17
17
  cache_json
18
18
  return if skip_publish_json
19
- subscriptions = $redis.hgetall("jason:#{self.class.name.underscore}:subscriptions")
20
- subscriptions.each do |id, config_json|
19
+ self.class.jason_subscriptions.each do |id, config_json|
21
20
  config = JSON.parse(config_json)
22
21
 
23
22
  if (config['conditions'] || {}).all? { |field, value| self.send(field) == value }
@@ -33,7 +32,11 @@ module Jason::Publisher
33
32
 
34
33
  class_methods do
35
34
  def subscriptions
36
- $redis.hgetall("jason:#{self.name.underscore}:subscriptions")
35
+ $redis_jason.hgetall("jason:#{self.name.underscore}:subscriptions")
36
+ end
37
+
38
+ def jason_subscriptions
39
+ $redis_jason.hgetall("jason:#{self.name.underscore}:subscriptions")
37
40
  end
38
41
 
39
42
  def publish_all(instances)
@@ -45,7 +48,7 @@ module Jason::Publisher
45
48
  end
46
49
 
47
50
  def flush_cache
48
- $redis.del("jason:#{self.name.underscore}:cache")
51
+ $redis_jason.del("jason:#{self.name.underscore}:cache")
49
52
  end
50
53
 
51
54
  def setup_json
@@ -69,6 +72,35 @@ module Jason::Publisher
69
72
  }
70
73
  end
71
74
  end
75
+
76
+ def find_or_create_by_id(params)
77
+ object = find_by(id: params[:id])
78
+
79
+ if object
80
+ object.update(params)
81
+ elsif params[:hidden]
82
+ return false ## If an object is passed with hidden = true but didn't already exist, it's safe to never create it
83
+ else
84
+ object = create!(params)
85
+ end
86
+
87
+ object
88
+ end
89
+
90
+ def find_or_create_by_id!(params)
91
+ object = find_by(id: params[:id])
92
+
93
+ if object
94
+ object.update!(params)
95
+ elsif params[:hidden]
96
+ ## 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.
97
+ return false ## If an object is passed with hidden = true but didn't already exist, it's safe to never create it
98
+ else
99
+ object = create!(params)
100
+ end
101
+
102
+ object
103
+ end
72
104
  end
73
105
 
74
106
  included do
@@ -4,7 +4,7 @@ class Jason::Subscription
4
4
  def initialize(id: nil, config: nil)
5
5
  if id
6
6
  @id = id
7
- raw_config = $redis.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.with_indifferent_access
8
8
  set_config(raw_config)
9
9
  else
10
10
  @id = Digest::MD5.hexdigest(config.to_json)
@@ -18,30 +18,28 @@ class Jason::Subscription
18
18
 
19
19
  def configure(raw_config)
20
20
  set_config(raw_config)
21
- $redis.hmset("jason:subscriptions:#{id}", *config.map { |k,v| [k, v.to_json]}.flatten)
21
+ $redis_jason.hmset("jason:subscriptions:#{id}", *config.map { |k,v| [k, v.to_json]}.flatten)
22
22
  end
23
23
 
24
24
  def destroy
25
25
  config.each do |model, value|
26
- $redis.srem("jason:#{model.to_s.underscore}:subscriptions", id)
26
+ $redis_jason.srem("jason:#{model.to_s.underscore}:subscriptions", id)
27
27
  end
28
- $redis.del("jason:subscriptions:#{id}")
28
+ $redis_jason.del("jason:subscriptions:#{id}")
29
29
  end
30
30
 
31
31
  def add_consumer(consumer_id)
32
32
  before_consumer_count = consumer_count
33
- $redis.sadd("jason:subscriptions:#{id}:consumers", consumer_id)
34
- $redis.hset("jason:consumers", consumer_id, Time.now.utc)
33
+ $redis_jason.sadd("jason:subscriptions:#{id}:consumers", consumer_id)
34
+ $redis_jason.hset("jason:consumers", consumer_id, Time.now.utc)
35
35
 
36
- if before_consumer_count == 0
37
- add_subscriptions
38
- publish_all
39
- end
36
+ add_subscriptions
37
+ publish_all
40
38
  end
41
39
 
42
40
  def remove_consumer(consumer_id)
43
- $redis.srem("jason:subscriptions:#{id}:consumers", consumer_id)
44
- $redis.hdel("jason:consumers", consumer_id)
41
+ $redis_jason.srem("jason:subscriptions:#{id}:consumers", consumer_id)
42
+ $redis_jason.hdel("jason:consumers", consumer_id)
45
43
 
46
44
  if consumer_count == 0
47
45
  remove_subscriptions
@@ -49,7 +47,7 @@ class Jason::Subscription
49
47
  end
50
48
 
51
49
  def consumer_count
52
- $redis.scard("jason:subscriptions:#{id}:consumers")
50
+ $redis_jason.scard("jason:subscriptions:#{id}:consumers")
53
51
  end
54
52
 
55
53
  def channel
@@ -67,14 +65,14 @@ class Jason::Subscription
67
65
 
68
66
  def add_subscriptions
69
67
  config.each do |model, value|
70
- $redis.hset("jason:#{model.to_s.underscore}:subscriptions", id, value.to_json)
68
+ $redis_jason.hset("jason:#{model.to_s.underscore}:subscriptions", id, value.to_json)
71
69
  update(model)
72
70
  end
73
71
  end
74
72
 
75
73
  def remove_subscriptions
76
74
  config.each do |model, _|
77
- $redis.hdel("jason:#{model.to_s.underscore}:subscriptions", id)
75
+ $redis_jason.hdel("jason:#{model.to_s.underscore}:subscriptions", id)
78
76
  end
79
77
  end
80
78
 
@@ -86,8 +84,8 @@ class Jason::Subscription
86
84
  end
87
85
 
88
86
  def get(model)
89
- value = JSON.parse($redis.get("#{channel}:#{model}:value") || '{}')
90
- idx = $redis.get("#{channel}:#{model}:idx").to_i
87
+ value = JSON.parse($redis_jason.get("#{channel}:#{model}:value") || '[]')
88
+ idx = $redis_jason.get("#{channel}:#{model}:idx").to_i
91
89
 
92
90
  {
93
91
  type: 'payload',
@@ -113,7 +111,7 @@ class Jason::Subscription
113
111
  def get_throttle
114
112
  if !$throttle_rate || !$throttle_timeout || Time.now.utc > $throttle_timeout
115
113
  $throttle_timeout = Time.now.utc + 5.seconds
116
- $throttle_rate = (Sidekiq.redis { |r| r.get 'global_throttle_rate' } || 0).to_i
114
+ $throttle_rate = ($redis_jason.get('global_throttle_rate') || 0).to_i
117
115
  else
118
116
  $throttle_rate
119
117
  end
@@ -124,15 +122,15 @@ class Jason::Subscription
124
122
  start_time = Time.now.utc
125
123
  conditions = config[model]['conditions']
126
124
 
127
- value = $redis.hgetall("jason:#{model}:cache")
125
+ value = $redis_jason.hgetall("jason:#{model}:cache")
128
126
  .values.map { |v| JSON.parse(v) }
129
127
  .select { |v| (conditions || {}).all? { |field, value| v[field] == value } }
130
128
  .sort_by { |v| v['id'] }
131
129
 
132
130
  # lfsa = last finished, started at
133
131
  # If another job that started after this one, finished before this one, skip sending this state update
134
- if Time.parse(Sidekiq.redis { |r| r.get("jason:#{channel}:lfsa") || '1970-01-01 00:00:00 UTC' } ) < start_time
135
- Sidekiq.redis { |r| r.set("jason:#{channel}:lfsa", start_time) }
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)
136
134
  else
137
135
  return
138
136
  end
@@ -149,12 +147,11 @@ class Jason::Subscription
149
147
  end
150
148
  LUA
151
149
 
152
- result = $redis.eval cmd, [], ["#{channel}:#{model}", value.to_json]
150
+ result = $redis_jason.eval cmd, [], ["#{channel}:#{model}", value.to_json]
153
151
  return if result.blank?
154
152
 
155
153
  idx = result[0]
156
- old_value = JSON.parse(result[1] || '{}')
157
-
154
+ old_value = JSON.parse(result[1] || '[]')
158
155
  diff = get_diff(old_value, value)
159
156
 
160
157
  end_time = Time.now.utc
@@ -1,3 +1,3 @@
1
1
  module Jason
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,15 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jason-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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-04 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-12-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: connection_pool
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: jsondiff
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  description:
14
70
  email:
15
71
  - jarees@gmail.com
@@ -22,11 +78,22 @@ files:
22
78
  - ".travis.yml"
23
79
  - CODE_OF_CONDUCT.md
24
80
  - Gemfile
81
+ - Gemfile.lock
25
82
  - LICENSE.txt
26
83
  - README.md
27
84
  - Rakefile
85
+ - app/assets/config/jason_engine_manifest.js
86
+ - app/assets/images/jason/engine/.keep
87
+ - app/assets/stylesheets/jason/engine/application.css
88
+ - 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
28
94
  - bin/console
29
95
  - bin/setup
96
+ - client/babel.config.js
30
97
  - client/lib/JasonContext.d.ts
31
98
  - client/lib/JasonContext.js
32
99
  - client/lib/JasonProvider.d.ts
@@ -37,8 +104,14 @@ files:
37
104
  - client/lib/createActions.js
38
105
  - client/lib/createJasonReducers.d.ts
39
106
  - client/lib/createJasonReducers.js
107
+ - client/lib/createOptDis.d.ts
108
+ - client/lib/createOptDis.js
40
109
  - client/lib/createPayloadHandler.d.ts
41
110
  - client/lib/createPayloadHandler.js
111
+ - client/lib/deepCamelizeKeys.d.ts
112
+ - client/lib/deepCamelizeKeys.js
113
+ - client/lib/deepCamelizeKeys.test.d.ts
114
+ - client/lib/deepCamelizeKeys.test.js
42
115
  - client/lib/index.d.ts
43
116
  - client/lib/index.js
44
117
  - client/lib/makeEager.d.ts
@@ -53,17 +126,22 @@ files:
53
126
  - client/src/actionFactory.ts
54
127
  - client/src/createActions.ts
55
128
  - client/src/createJasonReducers.ts
129
+ - client/src/createOptDis.ts
56
130
  - client/src/createPayloadHandler.ts
131
+ - client/src/deepCamelizeKeys.test.ts
132
+ - client/src/deepCamelizeKeys.ts
57
133
  - client/src/index.ts
58
134
  - client/src/makeEager.ts
59
135
  - client/src/useAct.ts
60
136
  - client/src/useSub.ts
61
137
  - client/tsconfig.json
62
138
  - client/yarn.lock
139
+ - config/routes.rb
63
140
  - jason-rails.gemspec
64
141
  - lib/jason.rb
65
142
  - lib/jason/api_model.rb
66
143
  - lib/jason/channel.rb
144
+ - lib/jason/engine.rb
67
145
  - lib/jason/publisher.rb
68
146
  - lib/jason/subscription.rb
69
147
  - lib/jason/version.rb