loco-rails 3.0.6 → 4.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79191fae751caacf8c4dc17551a62cb5fae5de5d69307afde0014c9c276a2d32
4
- data.tar.gz: 6bcf8149cf78be74b639a054bf1b59cac8d0c098abca76e4a4738b66cda70fe1
3
+ metadata.gz: 14ddadb549243851cfae8f6260dbe08b6813392116f03b83d4618615598ec2d3
4
+ data.tar.gz: c5cdfc9d981ce63a5e8237cb794d7eb2a9d8435941070bba84f65f188e08e215
5
5
  SHA512:
6
- metadata.gz: 5094696a9904e3e8a3a4ee41236aed45f818aeb87f7caf951bac577cd3c21b3f7e6c67377a32e7c31d926a6bc61d9ff0965ec4c93f8baef90f2ec67c22c5dc55
7
- data.tar.gz: 5df1a26fb32cb187eb2136e4e2a2b5b554bdd2d1d9ff158d5d0f52a0e24cfbe780f6d87099320a1ea023972d8661c760e87fb101006f6749c73f64370946ae9d
6
+ metadata.gz: '0921bb8ffff692bede6999ae0dc2de20d1822c0ca3b5a8bac0aabcd50909a12369a6987da6b309356e4306dfd3891aea85adff8c418cce1eacabc4bd73348509'
7
+ data.tar.gz: f8d9d259ae99c421bcbdbf03df5fa1878ae6dd590eb835d6c432a6c6e91b103df5d5efbcdfe9daff6ae1d4fbb2bab1c193d3416b1e6213b7e134842d7f2dea48
@@ -4,58 +4,62 @@ module Loco
4
4
  class NotificationCenterChannel < ApplicationCable::Channel
5
5
  def subscribed
6
6
  return unless loco_permissions.is_a?(Array)
7
+
7
8
  stream_for_resources
8
9
  return if loco_permissions.compact.size > 1
10
+
9
11
  SenderJob.perform_later @uuid, loco: { start_ajax_polling: true }
10
12
  end
11
13
 
12
14
  def unsubscribed
13
15
  loco_permissions.each do |resource|
14
16
  next if resource.nil? || resource.is_a?(String)
17
+
15
18
  UuidJob.perform_later serialize_resource(resource), @uuid, 'del'
16
19
  end
17
20
  end
18
21
 
19
- def receive data
22
+ def receive(data)
20
23
  update_connections if data['loco'] && data['loco']['connection_check']
21
- NotificationCenter.new.received_signal permissions, data
24
+ NotificationCenter.new.received_message permissions, data
22
25
  end
23
26
 
24
27
  protected
25
28
 
26
- def stream_for_resources
27
- loco_permissions.compact.each do |resource|
28
- if resource.is_a? String
29
- @uuid = resource
30
- stream_for_resource resource
31
- SenderJob.perform_later @uuid, loco: { uuid: @uuid }
32
- else
33
- UuidJob.perform_later serialize_resource(resource), @uuid, 'add'
34
- stream_for_resource resource
35
- end
29
+ def stream_for_resources
30
+ loco_permissions.compact.each do |resource|
31
+ if resource.is_a? String
32
+ @uuid = resource
33
+ stream_for_resource resource
34
+ SenderJob.perform_later @uuid, loco: { uuid: @uuid }
35
+ else
36
+ UuidJob.perform_later serialize_resource(resource), @uuid, 'add'
37
+ stream_for_resource resource
36
38
  end
37
39
  end
40
+ end
38
41
 
39
- def stream_for_resource resource
40
- identifier = WsConnectionManager.new(resource).identifier
41
- stream_from "loco:notification_center:#{identifier}"
42
- end
42
+ def stream_for_resource(resource)
43
+ identifier = WsConnectionManager.new(resource).identifier
44
+ stream_from "loco:notification_center:#{identifier}"
45
+ end
43
46
 
44
- def permissions
45
- loco_permissions.compact.map do |o|
46
- [o.class.name.downcase.to_sym, o]
47
- end.to_h
47
+ def permissions
48
+ loco_permissions.compact.index_by do |o|
49
+ o.class.name.downcase.to_sym
48
50
  end
51
+ end
49
52
 
50
- def update_connections
51
- permissions.each do |key, val|
52
- next if key == :string
53
- UuidJob.perform_later serialize_resource(val), @uuid, 'update'
54
- end
55
- end
53
+ def update_connections
54
+ permissions.each do |key, val|
55
+ next if key == :string
56
56
 
57
- def serialize_resource resource
58
- { 'class' => resource.class.name, 'id' => resource.id }
57
+ UuidJob.perform_later serialize_resource(val), @uuid, 'update'
59
58
  end
59
+ end
60
+
61
+ def serialize_resource(resource)
62
+ { 'class' => resource.class.name, 'id' => resource.id }
63
+ end
60
64
  end
61
65
  end
@@ -16,43 +16,46 @@ module Loco
16
16
 
17
17
  private
18
18
 
19
- def fetch_notifications
20
- if params[:synced_at].blank?
21
- render json: [[], Time.current.iso8601(6)]
22
- return
23
- end
24
- fetcher = Notification::Fetcher.new notif_fetcher_args
25
- render json: [
26
- fetcher.formatted_notifications,
27
- fetcher.next_sync_time.iso8601(6)
28
- ]
19
+ def fetch_notifications
20
+ if params[:synced_at].blank?
21
+ render json: [[], Time.current.iso8601(6)]
22
+ return
29
23
  end
24
+ fetcher = Notification::Fetcher.new notif_fetcher_args
25
+ render json: [
26
+ fetcher.formatted_notifications,
27
+ fetcher.next_sync_time.iso8601(6)
28
+ ]
29
+ end
30
30
 
31
- def notif_fetcher_args
32
- {
33
- synced_at: params[:synced_at],
34
- permissions: permissions,
35
- recipient_token: params[:token]
36
- }
37
- end
31
+ def notif_fetcher_args
32
+ {
33
+ synced_at: params[:synced_at],
34
+ permissions: permissions,
35
+ recipient_token: params[:token]
36
+ }
37
+ end
38
38
 
39
- def permissions
40
- return [] unless defined? loco_permissions
41
- return loco_permissions if params[:uuid].blank?
42
- process_loco_permissions
43
- end
39
+ def permissions
40
+ return [] unless defined? loco_permissions
41
+ return loco_permissions if params[:uuid].blank?
44
42
 
45
- def process_loco_permissions
46
- resources_to_del = []
47
- resources_to_add = []
48
- loco_permissions.each do |resource|
49
- next if resource.nil?
50
- ws_conn_manager = WsConnectionManager.new resource
51
- next unless ws_conn_manager.connected?(params[:uuid])
52
- resources_to_del << resource
53
- resources_to_add << resource.class
54
- end
55
- loco_permissions - resources_to_del + resources_to_add.uniq
43
+ process_loco_permissions
44
+ end
45
+
46
+ def process_loco_permissions
47
+ resources_to_del = []
48
+ resources_to_add = []
49
+ loco_permissions.each do |resource|
50
+ next if resource.nil?
51
+
52
+ ws_conn_manager = WsConnectionManager.new resource
53
+ next unless ws_conn_manager.connected?(params[:uuid])
54
+
55
+ resources_to_del << resource
56
+ resources_to_add << resource.class
56
57
  end
58
+ loco_permissions - resources_to_del + resources_to_add.uniq
59
+ end
57
60
  end
58
61
  end
@@ -4,7 +4,7 @@ module Loco
4
4
  class SenderJob < ActiveJob::Base
5
5
  queue_as :loco
6
6
 
7
- def perform recipient, data
7
+ def perform(recipient, data)
8
8
  Sender.new(recipient, data).emit
9
9
  end
10
10
  end
@@ -4,9 +4,10 @@ module Loco
4
4
  class UuidJob < ActiveJob::Base
5
5
  queue_as :loco
6
6
 
7
- def perform serialized_resource, uuid, action
7
+ def perform(serialized_resource, uuid, action)
8
8
  ws_conn_manager = init_ws_conn_manager serialized_resource
9
9
  return unless ws_conn_manager
10
+
10
11
  case action
11
12
  when 'add'
12
13
  add ws_conn_manager, uuid
@@ -19,30 +20,32 @@ module Loco
19
20
 
20
21
  protected
21
22
 
22
- def add ws_conn_manager, uuid
23
- ws_conn_manager.add uuid
24
- WsConnectedResourcesManager.add ws_conn_manager.identifier
25
- end
23
+ def add(ws_conn_manager, uuid)
24
+ ws_conn_manager.add uuid
25
+ WsConnectedResourcesManager.add ws_conn_manager.identifier
26
+ end
26
27
 
27
- def del ws_conn_manager, uuid
28
- ws_conn_manager.del uuid
29
- return if ws_conn_manager.connected_uuids.any?
30
- WsConnectedResourcesManager.del ws_conn_manager.identifier
31
- end
28
+ def del(ws_conn_manager, uuid)
29
+ ws_conn_manager.del uuid
30
+ return if ws_conn_manager.connected_uuids.any?
32
31
 
33
- def update ws_conn_manager, uuid
34
- ws_conn_manager.update uuid
35
- WsConnectedResourcesManager.add ws_conn_manager.identifier
36
- end
32
+ WsConnectedResourcesManager.del ws_conn_manager.identifier
33
+ end
37
34
 
38
- def deserialize_resource hash
39
- hash['class'].constantize.find_by id: hash['id']
40
- end
35
+ def update(ws_conn_manager, uuid)
36
+ ws_conn_manager.update uuid
37
+ WsConnectedResourcesManager.add ws_conn_manager.identifier
38
+ end
41
39
 
42
- def init_ws_conn_manager serialized_resource
43
- resource = deserialize_resource serialized_resource
44
- return unless resource
45
- WsConnectionManager.new resource
46
- end
40
+ def deserialize_resource(hash)
41
+ hash['class'].constantize.find_by id: hash['id']
42
+ end
43
+
44
+ def init_ws_conn_manager(serialized_resource)
45
+ resource = deserialize_resource serialized_resource
46
+ return unless resource
47
+
48
+ WsConnectionManager.new resource
49
+ end
47
50
  end
48
51
  end
@@ -17,7 +17,7 @@ module Loco
17
17
  end
18
18
  end
19
19
 
20
- def obj= val
20
+ def obj=(val)
21
21
  if val.instance_of? Class
22
22
  self.obj_class = val.to_s
23
23
  else
@@ -27,9 +27,10 @@ module Loco
27
27
  end
28
28
  end
29
29
 
30
- def recipient= val
30
+ def recipient=(val)
31
31
  return if val.nil?
32
32
  return if val == :all
33
+
33
34
  if val.is_a? String
34
35
  self.recipient_token = val
35
36
  elsif val.instance_of? Class
@@ -40,10 +41,11 @@ module Loco
40
41
  end
41
42
  end
42
43
 
43
- def recipient opts = {}
44
+ def recipient(opts = {})
44
45
  return recipient_token if recipient_token
45
46
  return unless regular_recipient?
46
47
  return class_recipient unless recipient_id
48
+
47
49
  obj_recipient opts[:shallow]
48
50
  end
49
51
 
@@ -58,40 +60,42 @@ module Loco
58
60
 
59
61
  private
60
62
 
61
- def regular_recipient?
62
- recipient_class && recipient_id
63
- end
63
+ def regular_recipient?
64
+ recipient_class && recipient_id
65
+ end
64
66
 
65
- def class_recipient
66
- recipient_class.constantize
67
- end
67
+ def class_recipient
68
+ recipient_class.constantize
69
+ end
68
70
 
69
- def obj_recipient shallow = false
70
- if shallow
71
- recipient_class.constantize.new id: recipient_id
72
- else
73
- recipient_class.constantize.find recipient_id
74
- end
71
+ def obj_recipient(shallow = false)
72
+ if shallow
73
+ recipient_class.constantize.new id: recipient_id
74
+ else
75
+ recipient_class.constantize.find recipient_id
75
76
  end
77
+ end
76
78
 
77
- def set_event
78
- return if event.present?
79
- return if obj.instance_of? Class
80
- if obj.new_record?
81
- self.event = 'creating'
82
- else
83
- set_event_for_persisted_obj
84
- end
85
- end
79
+ def set_event
80
+ return if event.present?
81
+ return if obj.instance_of? Class
86
82
 
87
- def set_event_for_persisted_obj
88
- self.event = obj.created_at == obj.updated_at ? 'created' : 'updated'
83
+ if obj.new_record?
84
+ self.event = 'creating'
85
+ else
86
+ set_event_for_persisted_obj
89
87
  end
88
+ end
90
89
 
91
- def set_data
92
- self.data ||= {}
93
- return if obj.nil?
94
- self.data.merge!(id: obj.id)
95
- end
90
+ def set_event_for_persisted_obj
91
+ self.event = obj.created_at == obj.updated_at ? 'created' : 'updated'
92
+ end
93
+
94
+ def set_data
95
+ self.data ||= {}
96
+ return if obj.nil?
97
+
98
+ self.data.merge!(id: obj.id)
99
+ end
96
100
  end
97
101
  end
@@ -32,56 +32,58 @@ module Loco
32
32
 
33
33
  private
34
34
 
35
- def sync_time
36
- Time.zone.parse @synced_at
37
- end
35
+ def sync_time
36
+ Time.zone.parse @synced_at
37
+ end
38
38
 
39
- def default_scope
40
- Notification.order('created_at ASC')
41
- .where('created_at > ?', sync_time)
42
- end
39
+ def default_scope
40
+ Notification.order('created_at ASC')
41
+ .where('created_at > ?', sync_time)
42
+ end
43
43
 
44
- # OPTIMIZE: one query
45
- def notifications
46
- return @notifications if @notifications
47
- notifications = notifications_for_all
48
- notifications += notifications_behind_permissions
49
- notifications += notifications_behind_token if @recipient_token
50
- @notifications = notifications.sort_by(&:created_at)[0, max_size]
51
- end
44
+ # OPTIMIZE: one query
45
+ def notifications
46
+ return @notifications if @notifications
52
47
 
53
- def notifications_for_all
54
- default_scope.where(
55
- recipient_class: nil,
56
- recipient_id: nil,
57
- recipient_token: nil
58
- ).first max_size
59
- end
48
+ notifications = notifications_for_all
49
+ notifications += notifications_behind_permissions
50
+ notifications += notifications_behind_token if @recipient_token
51
+ @notifications = notifications.sort_by(&:created_at)[0, max_size]
52
+ end
60
53
 
61
- def notifications_behind_permissions
62
- notifications = []
63
- @permissions.each do |resource|
64
- next unless resource
65
- notifications += notification_for_resource resource
66
- end
67
- notifications
68
- end
54
+ def notifications_for_all
55
+ default_scope.where(
56
+ recipient_class: nil,
57
+ recipient_id: nil,
58
+ recipient_token: nil
59
+ ).first max_size
60
+ end
69
61
 
70
- def notifications_behind_token
71
- default_scope.where(recipient_token: @recipient_token).first max_size
62
+ def notifications_behind_permissions
63
+ notifications = []
64
+ @permissions.each do |resource|
65
+ next unless resource
66
+
67
+ notifications += notification_for_resource resource
72
68
  end
69
+ notifications
70
+ end
73
71
 
74
- def notification_for_resource resource
75
- if resource.instance_of? Class
76
- sql = 'recipient_class = ? AND recipient_id IS NULL'
77
- return default_scope.where(sql, resource.to_s).first max_size
78
- end
79
- klass = resource.class.name
80
- cond1 = '(recipient_class = ? AND recipient_id = ?)'
81
- cond2 = '(recipient_class = ? AND recipient_id IS NULL)'
82
- sql = "#{cond1} OR #{cond2}"
83
- default_scope.where(sql, klass, resource.id, klass).first max_size
72
+ def notifications_behind_token
73
+ default_scope.where(recipient_token: @recipient_token).first max_size
74
+ end
75
+
76
+ def notification_for_resource(resource)
77
+ if resource.instance_of? Class
78
+ sql = 'recipient_class = ? AND recipient_id IS NULL'
79
+ return default_scope.where(sql, resource.to_s).first max_size
84
80
  end
81
+ klass = resource.class.name
82
+ cond1 = '(recipient_class = ? AND recipient_id = ?)'
83
+ cond2 = '(recipient_class = ? AND recipient_id IS NULL)'
84
+ sql = "#{cond1} OR #{cond2}"
85
+ default_scope.where(sql, klass, resource.id, klass).first max_size
86
+ end
85
87
  end
86
88
  end
87
89
  end
@@ -5,30 +5,21 @@ module Loco
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  def routes
8
- file_path = Rails.root.join 'config', 'routes.rb'
8
+ file_path = Rails.root.join 'config/routes.rb'
9
9
  line = %( mount Loco::Engine => '/notification-center'\n\n)
10
10
  str = "Rails.application.routes.draw do\n"
11
11
  inject_into_file file_path, line, after: str
12
12
  end
13
13
 
14
14
  def application_controller
15
- file_path = Rails.root.join(
16
- 'app',
17
- 'controllers',
18
- 'application_controller.rb'
19
- )
15
+ file_path = Rails.root.join 'app/controllers/application_controller.rb'
20
16
  data = File.read find_in_source_paths('application_controller.rb')
21
17
  after_line = "class ApplicationController < ActionController::Base\n"
22
18
  inject_into_file file_path, data, after: after_line
23
19
  end
24
20
 
25
21
  def connection
26
- file_path = Rails.root.join(
27
- 'app',
28
- 'channels',
29
- 'application_cable',
30
- 'connection.rb'
31
- )
22
+ file_path = Rails.root.join 'app/channels/application_cable/connection.rb'
32
23
  data = File.read find_in_source_paths('connection.rb')
33
24
  inject_into_class file_path, 'Connection', data
34
25
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Loco::Config.configure(
4
- silence_logger: false, # false by default
5
- notifications_size: 100, # 100 by default
6
- app_name: "loco_#{Rails.env}" # your app's name (required for namespacing)
7
- )
3
+ Loco.configure do |c|
4
+ c.silence_logger = false # false by default
5
+ c.notifications_size = 100 # 100 by default
6
+ c.app_name = "loco_#{Rails.env}" # your app's name (required for namespacing)
7
+ end
@@ -1,5 +1,5 @@
1
1
  Description:
2
- Creates a notification center where you can receive signals sent by JS clients through WebSockets.
2
+ Creates a notification center where you can receive messages sent by JS clients through WebSockets.
3
3
 
4
4
  Example:
5
5
  rails generate loco:notification_center
@@ -4,8 +4,8 @@ module Loco
4
4
  class NotificationCenter
5
5
  include Emitter
6
6
 
7
- def received_signal permissions, data
8
- # handle signals here
7
+ def received_message(permissions, data)
8
+ # handle messages here
9
9
  end
10
10
  end
11
11
  end
@@ -14,4 +14,12 @@ require 'loco/ws_connected_resources_manager'
14
14
  require 'loco/ws_connection_storage'
15
15
 
16
16
  module Loco
17
+ module_function
18
+
19
+ def configure
20
+ Config::CONFIGURATION.new.tap do |config|
21
+ yield config
22
+ Config.configure config
23
+ end
24
+ end
17
25
  end
@@ -4,7 +4,7 @@ module Loco
4
4
  class Broadcaster
5
5
  attr_reader :obj, :event, :recipients, :data, :notifications
6
6
 
7
- def initialize obj, event = nil, opts = {}
7
+ def initialize(obj, event = nil, opts = {})
8
8
  recipient_key = opts[:for] ? :for : :to
9
9
  @obj = obj
10
10
  @event = event
@@ -15,15 +15,6 @@ module Loco
15
15
  @conn_res_manager = WsConnectedResourcesManager.new @recipients.compact
16
16
  end
17
17
 
18
- def signals
19
- notifications
20
- end
21
-
22
- def prepare
23
- init_notifications if notifications.empty?
24
- prepare_notifications
25
- end
26
-
27
18
  def emit
28
19
  init_notifications if notifications.empty?
29
20
  send_notifications
@@ -36,77 +27,76 @@ module Loco
36
27
 
37
28
  private
38
29
 
39
- def init_notifications
40
- recipients.each do |recipient|
41
- @notifications << Notification.new(
42
- obj: obj,
43
- event: event,
44
- recipient: recipient,
45
- data: data
46
- )
47
- end
30
+ def init_notifications
31
+ recipients.each do |recipient|
32
+ @notifications << Notification.new(
33
+ obj: obj,
34
+ event: event,
35
+ recipient: recipient,
36
+ data: data
37
+ )
48
38
  end
39
+ end
49
40
 
50
- def prepare_notifications
51
- notifications.each(&:prepare)
52
- end
41
+ def send_notifications
42
+ notifications.each do |notification|
43
+ notification.save!
44
+ next if notification.recipient_id.nil?
53
45
 
54
- def send_notifications
55
- notifications.each do |notification|
56
- notification.save!
57
- next if notification.recipient_id.nil?
58
- shallow_recipient = notification.recipient shallow: true
59
- next unless @conn_res_manager.connected? shallow_recipient
60
- send_via_ws notification
61
- end
62
- end
46
+ shallow_recipient = notification.recipient shallow: true
47
+ next unless @conn_res_manager.connected? shallow_recipient
63
48
 
64
- def send_via_ws notification
65
- recipient = notification.recipient shallow: true
66
- data = { loco: { notification: notification.compact } }
67
- SenderJob.perform_later recipient, data
68
- @sent_via_ws += 1
49
+ send_via_ws notification
69
50
  end
51
+ end
70
52
 
71
- def notify_about_xhr_notifications?
72
- @sent_via_ws < notifications.size
73
- end
53
+ def send_via_ws(notification)
54
+ recipient = notification.recipient shallow: true
55
+ data = { loco: { notification: notification.compact } }
56
+ SenderJob.perform_later recipient, data
57
+ @sent_via_ws += 1
58
+ end
59
+
60
+ def notify_about_xhr_notifications?
61
+ @sent_via_ws < notifications.size
62
+ end
63
+
64
+ def notify_about_xhr_notifications
65
+ uuids = []
66
+ fetch_identifiers.each do |ident|
67
+ Loco::WsConnectionManager.new(ident).connected_uuids.each do |uuid|
68
+ next if uuids.include? uuid
74
69
 
75
- def notify_about_xhr_notifications
76
- uuids = []
77
- fetch_identifiers.each do |ident|
78
- Loco::WsConnectionManager.new(ident).connected_uuids.each do |uuid|
79
- next if uuids.include? uuid
80
- uuids << uuid
81
- SenderJob.perform_later uuid, loco: { xhr_notifications: true }
82
- end
70
+ uuids << uuid
71
+ SenderJob.perform_later uuid, loco: { xhr_notifications: true }
83
72
  end
84
73
  end
74
+ end
85
75
 
86
- def set_sync_time_via_ws
87
- sync_time = notifications.last.created_at.iso8601(6)
88
- notifications.each do |notification|
89
- recipient = notification.recipient shallow: true
90
- SenderJob.perform_later recipient, loco: { sync_time: sync_time }
91
- end
76
+ def set_sync_time_via_ws
77
+ sync_time = notifications.last.created_at.iso8601(6)
78
+ notifications.each do |notification|
79
+ recipient = notification.recipient shallow: true
80
+ SenderJob.perform_later recipient, loco: { sync_time: sync_time }
92
81
  end
82
+ end
93
83
 
94
- def notifications_recipients
95
- notifications.map { |n| n.recipient shallow: true }.map do |o|
96
- o.instance_of?(Class) ? o.to_s.downcase : nil
97
- end
84
+ def notifications_recipients
85
+ notifications.map { |n| n.recipient shallow: true }.map do |o|
86
+ o.instance_of?(Class) ? o.to_s.downcase : nil
98
87
  end
88
+ end
99
89
 
100
- def fetch_identifiers
101
- recipients = notifications_recipients
102
- uniq_recipients = recipients.compact.uniq
103
- Loco::WsConnectedResourcesManager.identifiers.find_all do |str|
104
- if recipients.include? nil
105
- true
106
- else
107
- uniq_recipients.include? str.split(':').first
108
- end
90
+ def fetch_identifiers
91
+ recipients = notifications_recipients
92
+ uniq_recipients = recipients.compact.uniq
93
+ Loco::WsConnectedResourcesManager.identifiers.find_all do |str|
94
+ if recipients.include? nil
95
+ true
96
+ else
97
+ uniq_recipients.include? str.split(':').first
109
98
  end
110
99
  end
100
+ end
111
101
  end
112
102
  end
@@ -2,28 +2,29 @@
2
2
 
3
3
  module Loco
4
4
  class Config
5
+ CONFIGURATION = Struct.new :silence_logger, :notifications_size, :app_name, :redis_instance
6
+
5
7
  cattr_accessor(:silence_logger) { false }
6
8
  cattr_accessor(:notifications_size) { 100 }
7
9
  cattr_accessor(:app_name) { 'loco' }
8
10
  cattr_accessor(:redis_instance) { nil }
9
11
 
10
- def self.configure opts = {}
11
- self.silence_logger = opts[:silence_logger] if opts[:silence_logger]
12
- if opts[:notifications_size]
13
- self.notifications_size = opts[:notifications_size]
14
- end
15
- self.app_name = opts[:app_name] if opts[:app_name]
16
- configure_redis opts[:redis_instance]
12
+ def self.configure(config)
13
+ self.silence_logger = config.silence_logger if config.silence_logger
14
+ self.notifications_size = config.notifications_size if config.notifications_size
15
+ self.app_name = config.app_name if config.app_name
16
+ configure_redis config.redis_instance
17
17
  ensure
18
18
  true
19
19
  end
20
20
 
21
- def self.configure_redis redis_instance
21
+ def self.configure_redis(redis_instance)
22
22
  if redis_instance
23
23
  self.redis_instance = redis_instance
24
24
  return
25
25
  end
26
26
  return unless defined? Redis
27
+
27
28
  Redis.current.get 'random_redis_key'
28
29
  self.redis_instance = Redis.current
29
30
  rescue Redis::CannotConnectError
@@ -2,25 +2,26 @@
2
2
 
3
3
  module Loco
4
4
  module Emitter
5
- def emit obj, event = nil, opts = {}
5
+ def emit(obj, event = nil, opts = {})
6
6
  Broadcaster.new(obj, event, opts).emit
7
7
  end
8
8
 
9
- def emit_to recipient, data
9
+ def emit_to(recipient, data)
10
10
  Sender.new(recipient, data).emit
11
11
  end
12
12
 
13
- def add_hub name, members = []
13
+ def add_hub(name, members = [])
14
14
  Hub.new(name, members).save
15
15
  end
16
16
 
17
- def get_hub name
17
+ def get_hub(name)
18
18
  Hub.get name
19
19
  end
20
20
 
21
- def del_hub name
21
+ def del_hub(name)
22
22
  hub = Hub.get name
23
23
  return false if hub.nil?
24
+
24
25
  hub.destroy
25
26
  end
26
27
  end
@@ -6,15 +6,16 @@ module Loco
6
6
 
7
7
  attr_reader :raw_members
8
8
 
9
- def initialize name, members = []
9
+ def initialize(name, members = [])
10
10
  @name = "#{PREFIX}#{name}"
11
11
  @raw_members = members.map { |m| serialize m }
12
12
  end
13
13
 
14
14
  class << self
15
- def get name
15
+ def get(name)
16
16
  hub = WsConnectionStorage.current.get "#{PREFIX}#{name}"
17
17
  return nil if hub.blank?
18
+
18
19
  new name, JSON.parse(hub)
19
20
  end
20
21
  end
@@ -23,17 +24,19 @@ module Loco
23
24
  @name.split(PREFIX).last
24
25
  end
25
26
 
26
- def add_member member
27
+ def add_member(member)
27
28
  serialized = serialize member
28
29
  return raw_members if raw_members.include? serialized
30
+
29
31
  raw_members << serialized
30
32
  save
31
33
  raw_members
32
34
  end
33
35
 
34
- def del_member member
36
+ def del_member(member)
35
37
  serialized = serialize member
36
38
  return nil unless raw_members.include? serialized
39
+
37
40
  raw_members.delete serialized
38
41
  save
39
42
  serialized
@@ -49,7 +52,7 @@ module Loco
49
52
  self
50
53
  end
51
54
 
52
- def include? resource
55
+ def include?(resource)
53
56
  raw_members.include? serialize(resource)
54
57
  end
55
58
 
@@ -62,8 +65,8 @@ module Loco
62
65
 
63
66
  private
64
67
 
65
- def serialize member
66
- WsConnectionManager.new(member).identifier
67
- end
68
+ def serialize(member)
69
+ WsConnectionManager.new(member).identifier
70
+ end
68
71
  end
69
72
  end
@@ -2,35 +2,43 @@
2
2
 
3
3
  module Loco
4
4
  class Sender
5
- def initialize recipient, data = {}
5
+ def initialize(recipient, data = {})
6
6
  @recipients = [*recipient]
7
7
  @data = data
8
8
  end
9
9
 
10
10
  def emit
11
11
  uuids.each do |uuid|
12
- NotificationCenterChannel.broadcast_to uuid, @data
12
+ NotificationCenterChannel.broadcast_to(uuid, payload)
13
13
  end
14
+ @data[:loco][:idempotency_key]
14
15
  end
15
16
 
16
17
  private
17
18
 
18
- def uuids
19
- @recipients.map do |r|
20
- if r.is_a? String
21
- r
22
- elsif r.is_a? Hub
23
- recipients_from_hub r
24
- else
25
- WsConnectionManager.new(r).connected_uuids
26
- end
27
- end.flatten.uniq
28
- end
19
+ def uuids
20
+ @recipients.map do |r|
21
+ if r.is_a? String
22
+ r
23
+ elsif r.is_a? Hub
24
+ recipients_from_hub r
25
+ else
26
+ WsConnectionManager.new(r).connected_uuids
27
+ end
28
+ end.flatten.uniq
29
+ end
29
30
 
30
- def recipients_from_hub hub
31
- hub.raw_members.map do |m|
32
- WsConnectionManager.new(m).connected_uuids
33
- end.flatten.uniq
34
- end
31
+ def recipients_from_hub(hub)
32
+ hub.raw_members.map do |m|
33
+ WsConnectionManager.new(m).connected_uuids
34
+ end.flatten.uniq
35
+ end
36
+
37
+ def payload
38
+ @data[:loco] ||= {}
39
+ @data[:loco][:idempotency_key] ||= @data[:idempotency_key] || SecureRandom.hex
40
+ @data.delete(:idempotency_key)
41
+ @data
42
+ end
35
43
  end
36
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loco
4
- VERSION = '3.0.6'
4
+ VERSION = '4.0.0'
5
5
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Loco
4
4
  class WsConnectedResourcesManager
5
- def initialize resources
5
+ def initialize(resources)
6
6
  @resources = resources
7
7
  @connected_resources = nil
8
8
  end
@@ -11,19 +11,22 @@ module Loco
11
11
  def identifiers
12
12
  val = WsConnectionStorage.current.get key
13
13
  return [] if val.blank?
14
+
14
15
  JSON.parse val
15
16
  end
16
17
 
17
- def add identifier
18
+ def add(identifier)
18
19
  ids = identifiers
19
20
  return if ids.include? identifier
21
+
20
22
  ids << identifier
21
23
  WsConnectionStorage.current.set key, ids.to_json
22
24
  end
23
25
 
24
- def del identifier
26
+ def del(identifier)
25
27
  ids = identifiers
26
28
  return unless ids.include? identifier
29
+
27
30
  ids.delete identifier
28
31
  WsConnectionStorage.current.set key, ids.to_json
29
32
  end
@@ -35,14 +38,16 @@ module Loco
35
38
 
36
39
  def connected_resources
37
40
  return @connected_resources if @connected_resources
41
+
38
42
  @resources.each do |resource|
39
43
  next if WsConnectionManager.new(resource).connected_uuids.empty?
44
+
40
45
  add resource
41
46
  end
42
47
  @connected_resources || []
43
48
  end
44
49
 
45
- def connected? resource
50
+ def connected?(resource)
46
51
  connected_resources.map do |res|
47
52
  WsConnectionManager.new(res).identifier
48
53
  end.include? WsConnectionManager.new(resource).identifier
@@ -50,10 +55,10 @@ module Loco
50
55
 
51
56
  private
52
57
 
53
- def add resource
54
- @connected_resources ||= []
55
- @connected_resources << resource
56
- @connected_resources.uniq!
57
- end
58
+ def add(resource)
59
+ @connected_resources ||= []
60
+ @connected_resources << resource
61
+ @connected_resources.uniq!
62
+ end
58
63
  end
59
64
  end
@@ -2,16 +2,17 @@
2
2
 
3
3
  module Loco
4
4
  class WsConnectionManager
5
- def initialize resource
5
+ def initialize(resource)
6
6
  @resource = resource
7
7
  end
8
8
 
9
9
  def identifier
10
10
  return @resource if @resource.is_a?(String)
11
+
11
12
  "#{@resource.class.name.downcase}:#{@resource.id}"
12
13
  end
13
14
 
14
- def connected? uuid
15
+ def connected?(uuid)
15
16
  connected_uuids.include? uuid
16
17
  end
17
18
 
@@ -19,17 +20,17 @@ module Loco
19
20
  data.find_all { |_, v| v.is_a? String }.to_h.keys
20
21
  end
21
22
 
22
- def add uuid
23
+ def add(uuid)
23
24
  update uuid
24
25
  check_connections
25
26
  end
26
27
 
27
- def del uuid
28
+ def del(uuid)
28
29
  save(data.tap { |h| h.delete uuid })
29
30
  check_connections
30
31
  end
31
32
 
32
- def update uuid
33
+ def update(uuid)
33
34
  save(data.tap { |h| h[uuid] = current_time })
34
35
  end
35
36
 
@@ -39,51 +40,54 @@ module Loco
39
40
 
40
41
  protected
41
42
 
42
- def data
43
- serialized_uuids = WsConnectionStorage.current.get identifier
44
- return {} if serialized_uuids.blank?
45
- JSON.parse serialized_uuids
46
- end
43
+ def data
44
+ serialized_uuids = WsConnectionStorage.current.get identifier
45
+ return {} if serialized_uuids.blank?
47
46
 
48
- def uuids
49
- data.keys
50
- end
47
+ JSON.parse serialized_uuids
48
+ end
51
49
 
52
- def save hash
53
- WsConnectionStorage.current.set identifier, hash.to_json
54
- end
50
+ def uuids
51
+ data.keys
52
+ end
55
53
 
56
- def check_connections
57
- hash = data.to_a.map do |arr|
58
- uuid, val = check_connection arr.first, arr.last
59
- [uuid, val]
60
- end.to_h.compact
61
- save hash
62
- end
54
+ def save(hash)
55
+ WsConnectionStorage.current.set identifier, hash.to_json
56
+ end
63
57
 
64
- def check_connection uuid, val
65
- case val
66
- when String
67
- val = check_connection_str uuid, val
68
- when Hash
69
- uuid, val = check_connection_hash uuid, val
70
- end
58
+ def check_connections
59
+ hash = data.to_a.map do |arr|
60
+ uuid, val = check_connection arr.first, arr.last
71
61
  [uuid, val]
72
- end
62
+ end.to_h.compact
63
+ save hash
64
+ end
73
65
 
74
- def check_connection_str uuid, val
75
- return val if Time.zone.parse(val) >= 3.minutes.ago
76
- SenderJob.perform_later uuid, loco: { connection_check: true }
77
- { 'check' => current_time }
66
+ def check_connection(uuid, val)
67
+ case val
68
+ when String
69
+ val = check_connection_str uuid, val
70
+ when Hash
71
+ uuid, val = check_connection_hash uuid, val
78
72
  end
73
+ [uuid, val]
74
+ end
79
75
 
80
- def check_connection_hash uuid, val
81
- return [uuid, val] if Time.zone.parse(val['check']) >= 5.seconds.ago
82
- [nil, nil]
83
- end
76
+ def check_connection_str(uuid, val)
77
+ return val if Time.zone.parse(val) >= 3.minutes.ago
84
78
 
85
- def current_time
86
- Time.current.iso8601(6)
87
- end
79
+ SenderJob.perform_later uuid, loco: { connection_check: true }
80
+ { 'check' => current_time }
81
+ end
82
+
83
+ def check_connection_hash(uuid, val)
84
+ return [uuid, val] if Time.zone.parse(val['check']) >= 5.seconds.ago
85
+
86
+ [nil, nil]
87
+ end
88
+
89
+ def current_time
90
+ Time.current.iso8601(6)
91
+ end
88
92
  end
89
93
  end
@@ -16,7 +16,7 @@ module Loco
16
16
  @storage = Config.redis_instance || {}
17
17
  end
18
18
 
19
- def get key
19
+ def get(key)
20
20
  case @storage
21
21
  when Hash
22
22
  storage[proper_key(key)]
@@ -25,7 +25,7 @@ module Loco
25
25
  end
26
26
  end
27
27
 
28
- def set key, val
28
+ def set(key, val)
29
29
  case @storage
30
30
  when Hash
31
31
  storage[proper_key(key)] = val
@@ -34,7 +34,7 @@ module Loco
34
34
  end
35
35
  end
36
36
 
37
- def del key
37
+ def del(key)
38
38
  case @storage
39
39
  when Hash
40
40
  storage.delete proper_key(key)
@@ -45,8 +45,8 @@ module Loco
45
45
 
46
46
  protected
47
47
 
48
- def proper_key key
49
- "#{Config.app_name}:#{key}"
50
- end
48
+ def proper_key(key)
49
+ "#{Config.app_name}:#{key}"
50
+ end
51
51
  end
52
52
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loco-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.6
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zbigniew Humeniuk
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-15 00:00:00.000000000 Z
11
+ date: 2020-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: loco-rails-core
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.7.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: jbuilder
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.10.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.10.0
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: listen
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +120,14 @@ dependencies:
106
120
  requirements:
107
121
  - - "~>"
108
122
  - !ruby/object:Gem::Version
109
- version: 0.5.2
123
+ version: 0.5.3
110
124
  type: :development
111
125
  prerelease: false
112
126
  version_requirements: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - "~>"
115
129
  - !ruby/object:Gem::Version
116
- version: 0.5.2
130
+ version: 0.5.3
117
131
  - !ruby/object:Gem::Dependency
118
132
  name: puma
119
133
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +198,34 @@ dependencies:
184
198
  - - "~>"
185
199
  - !ruby/object:Gem::Version
186
200
  version: '3.142'
201
+ - !ruby/object:Gem::Dependency
202
+ name: source_maps_fixer
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ - !ruby/object:Gem::Dependency
216
+ name: will_paginate
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: 3.1.8
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: 3.1.8
187
229
  description: Rails is awesome, but modern web needs Loco-motive.
188
230
  email:
189
231
  - hello@artofcode.co
@@ -245,7 +287,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
245
287
  - !ruby/object:Gem::Version
246
288
  version: '0'
247
289
  requirements: []
248
- rubygems_version: 3.0.3
290
+ rubygems_version: 3.1.2
249
291
  signing_key:
250
292
  specification_version: 4
251
293
  summary: Framework on top of Rails.