tolliver 1.0.0 → 2.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 +4 -4
- data/README.md +21 -11
- data/app/models/tolliver/notification.rb +0 -1
- data/app/models/tolliver/notification_attachment.rb +16 -0
- data/app/models/tolliver/notification_delivery.rb +1 -3
- data/app/models/tolliver/notification_receiver.rb +0 -2
- data/app/models/tolliver/notification_template.rb +0 -1
- data/app/views/{notification_mailer → tolliver/notification_mailer}/notify.html.erb +0 -0
- data/app/views/tolliver/notification_mailer/notify.text.erb +1 -0
- data/config/locales/en.yml +1 -1
- data/db/migrate/20160121093817_create_notifications.rb +1 -12
- data/db/migrate/20160121094838_create_notification_receivers.rb +6 -4
- data/db/migrate/20160509144238_create_notification_templates.rb +4 -4
- data/db/migrate/20170630190600_create_notification_deliveries.rb +10 -3
- data/db/migrate/20201027150000_create_notification_attachments.rb +17 -0
- data/lib/tolliver.rb +44 -47
- data/lib/tolliver/errors/bad_request.rb +17 -0
- data/lib/tolliver/errors/not_found.rb +17 -0
- data/lib/tolliver/errors/standard_error.rb +17 -0
- data/lib/tolliver/mailers/notification_mailer.rb +10 -13
- data/lib/tolliver/models/notification.rb +11 -64
- data/lib/tolliver/models/notification_attachment.rb +35 -0
- data/lib/tolliver/models/notification_delivery.rb +32 -40
- data/lib/tolliver/models/notification_receiver.rb +3 -25
- data/lib/tolliver/models/notification_template.rb +6 -10
- data/lib/tolliver/services/delivery.rb +52 -8
- data/lib/tolliver/services/methods/email.rb +42 -0
- data/lib/tolliver/services/methods/sms.rb +51 -0
- data/lib/tolliver/services/methods/sms/plivo.rb +51 -0
- data/lib/tolliver/services/notification.rb +109 -178
- data/lib/tolliver/services/policies/batch.rb +90 -0
- data/lib/tolliver/services/policies/instantly.rb +50 -0
- metadata +20 -14
- data/app/views/notification_mailer/notify.text.erb +0 -1
- data/lib/tolliver/models/notification_delivery/batch.rb +0 -77
- data/lib/tolliver/models/notification_delivery/instantly.rb +0 -55
- data/lib/tolliver/models/notification_receiver/email.rb +0 -46
- data/lib/tolliver/models/notification_receiver/sms.rb +0 -45
- data/lib/tolliver/services/sms/plivo.rb +0 -49
@@ -0,0 +1,17 @@
|
|
1
|
+
# *****************************************************************************
|
2
|
+
# * Copyright (c) 2019 Matěj Outlý
|
3
|
+
# *****************************************************************************
|
4
|
+
# *
|
5
|
+
# * Standard error
|
6
|
+
# *
|
7
|
+
# * Author: Matěj Outlý
|
8
|
+
# * Date : 19. 4. 2017
|
9
|
+
# *
|
10
|
+
# *****************************************************************************
|
11
|
+
|
12
|
+
module Tolliver
|
13
|
+
module Errors
|
14
|
+
class StandardError < ::StandardError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -14,29 +14,26 @@ module Tolliver
|
|
14
14
|
module NotificationMailer
|
15
15
|
extend ActiveSupport::Concern
|
16
16
|
|
17
|
-
def notify(notification,
|
17
|
+
def notify(notification, notification_receiver)
|
18
18
|
|
19
19
|
# Sender
|
20
|
-
@
|
21
|
-
raise "Please specify sender." if @
|
22
|
-
|
23
|
-
@
|
20
|
+
@sender_email = Tolliver.email_sender
|
21
|
+
raise Tolliver::Errors::StandardError.new("Please specify sender.") if @sender_email.nil?
|
22
|
+
unless Tolliver.email_sender_name.blank?
|
23
|
+
@sender_email = "#{Tolliver.email_sender_name} <#{@sender_email}>"
|
24
24
|
end
|
25
25
|
|
26
26
|
# Other view data
|
27
27
|
@notification = notification
|
28
|
-
@
|
28
|
+
@notification_receiver = notification_receiver
|
29
29
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
# Attachment
|
34
|
-
if !notification.attachment.blank?
|
35
|
-
attachments[File.basename(notification.attachment)] = File.read(notification.attachment)
|
30
|
+
# Attachments
|
31
|
+
notification.notification_attachments.each do |notification_attachment|
|
32
|
+
attachments[notification_attachment.name] = notification_attachment.attachment
|
36
33
|
end
|
37
34
|
|
38
35
|
# Mail
|
39
|
-
mail(from: @
|
36
|
+
mail(from: @sender_email, to: @notification_receiver.receiver_contact, subject: @notification.subject)
|
40
37
|
end
|
41
38
|
|
42
39
|
end
|
@@ -21,14 +21,15 @@ module Tolliver
|
|
21
21
|
# *********************************************************************
|
22
22
|
|
23
23
|
has_many :notification_deliveries, class_name: Tolliver.notification_delivery_model.to_s, dependent: :destroy
|
24
|
-
|
24
|
+
has_many :notification_receivers, class_name: Tolliver.notification_receiver_model.to_s, through: :notification_deliveries
|
25
|
+
has_many :notification_attachments, class_name: Tolliver.notification_attachment_model.to_s, dependent: :destroy
|
25
26
|
belongs_to :notification_template, class_name: Tolliver.notification_template_model.to_s
|
26
27
|
|
27
28
|
# *********************************************************************
|
28
|
-
#
|
29
|
+
# Validators
|
29
30
|
# *********************************************************************
|
30
31
|
|
31
|
-
|
32
|
+
validates_presence_of :subject
|
32
33
|
|
33
34
|
end
|
34
35
|
|
@@ -43,77 +44,23 @@ module Tolliver
|
|
43
44
|
sent_count += notification_delivery.sent_count.to_i
|
44
45
|
receivers_count += notification_delivery.receivers_count.to_i
|
45
46
|
end
|
46
|
-
|
47
|
+
sent_count.to_s + "/" + receivers_count.to_s
|
47
48
|
end
|
48
49
|
|
49
50
|
# ***********************************************************************
|
50
|
-
#
|
51
|
+
# Service
|
51
52
|
# ***********************************************************************
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
if self.sender
|
56
|
-
if self.sender.respond_to?(:name_formatted) && !self.sender.name_formatted.blank?
|
57
|
-
return self.sender.name_formatted
|
58
|
-
elsif self.sender.respond_to?(:name) && !self.sender.name.blank?
|
59
|
-
return self.sender.name
|
60
|
-
else
|
61
|
-
return self.sender.email
|
62
|
-
end
|
63
|
-
else
|
64
|
-
return nil
|
65
|
-
end
|
54
|
+
def deliver
|
55
|
+
Tolliver::Services::Delivery.instance.deliver(self)
|
66
56
|
end
|
67
57
|
|
68
|
-
# ***********************************************************************
|
69
|
-
# Delivery
|
70
|
-
# ***********************************************************************
|
71
|
-
|
72
|
-
# Enqueue for delivery
|
73
58
|
def enqueue_for_delivery
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
# Deliver notification to receivers by all configured methods
|
78
|
-
def deliver
|
79
|
-
self.notification_deliveries.each do |notification_delivery|
|
80
|
-
notification_delivery.deliver
|
81
|
-
end
|
59
|
+
Tolliver::Services::Delivery.instance.enqueue_for_delivery(self)
|
82
60
|
end
|
83
61
|
|
84
|
-
|
85
|
-
|
86
|
-
# Deliver notification (defined by ID) to receivers by all configured methods
|
87
|
-
def deliver(notification_id)
|
88
|
-
|
89
|
-
# Find notification object
|
90
|
-
notification = Tolliver.notification_model.find_by_id(notification_id)
|
91
|
-
return nil if notification.nil?
|
92
|
-
|
93
|
-
# Load balance
|
94
|
-
if !Tolliver.load_balance.blank?
|
95
|
-
notifications_sent_in_protected_time_window = Tolliver.notification_model
|
96
|
-
.joins(:notification_deliveries)
|
97
|
-
.where.not(id: notification.id)
|
98
|
-
.where("notification_deliveries.sent_at > ?", Time.current - Tolliver.load_balance.minutes).distinct
|
99
|
-
if notifications_sent_in_protected_time_window.count > 0
|
100
|
-
|
101
|
-
# Sleep for given amount of time
|
102
|
-
sleep(Tolliver.load_balance * 60) # seconds
|
103
|
-
|
104
|
-
# Then try again
|
105
|
-
notification.enqueue_for_delivery
|
106
|
-
|
107
|
-
return notification
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Deliver
|
112
|
-
notification.deliver
|
113
|
-
|
114
|
-
return notification
|
115
|
-
end
|
116
|
-
|
62
|
+
def reset_delivery
|
63
|
+
Tolliver::Services::Delivery.instance.reset_delivery(self)
|
117
64
|
end
|
118
65
|
|
119
66
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# *****************************************************************************
|
2
|
+
# * Copyright (c) 2019 Matěj Outlý
|
3
|
+
# *****************************************************************************
|
4
|
+
# *
|
5
|
+
# * Notification attachment
|
6
|
+
# *
|
7
|
+
# * Author: Matěj Outlý
|
8
|
+
# * Date : 27. 10. 2020
|
9
|
+
# *
|
10
|
+
# *****************************************************************************
|
11
|
+
|
12
|
+
module Tolliver
|
13
|
+
module Models
|
14
|
+
module NotificationAttachment
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
included do
|
18
|
+
|
19
|
+
# *********************************************************************
|
20
|
+
# Structure
|
21
|
+
# *********************************************************************
|
22
|
+
|
23
|
+
belongs_to :notification, class_name: Tolliver.notification_model.to_s
|
24
|
+
|
25
|
+
# *********************************************************************
|
26
|
+
# Validators
|
27
|
+
# *********************************************************************
|
28
|
+
|
29
|
+
validates_presence_of :notification_id
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -27,13 +27,13 @@ module Tolliver
|
|
27
27
|
# Validators
|
28
28
|
# *********************************************************************
|
29
29
|
|
30
|
-
validates_presence_of :notification_id, :
|
30
|
+
validates_presence_of :notification_id, :method
|
31
31
|
|
32
32
|
# *********************************************************************
|
33
|
-
#
|
33
|
+
# Delivery method
|
34
34
|
# *********************************************************************
|
35
35
|
|
36
|
-
enum_column :
|
36
|
+
enum_column :method, Tolliver.delivery_methods
|
37
37
|
|
38
38
|
# *********************************************************************
|
39
39
|
# Queue kind
|
@@ -46,19 +46,37 @@ module Tolliver
|
|
46
46
|
|
47
47
|
end
|
48
48
|
|
49
|
+
# ***********************************************************************
|
50
|
+
# Delivery method
|
51
|
+
# ***********************************************************************
|
52
|
+
|
53
|
+
def method_service
|
54
|
+
if @method_service.nil?
|
55
|
+
@method_service = "Tolliver::Services::Methods::#{self.method.to_s.capitalize}".constantize.new
|
56
|
+
end
|
57
|
+
@method_service
|
58
|
+
end
|
59
|
+
|
49
60
|
# ***********************************************************************
|
50
61
|
# Policy
|
51
62
|
# ***********************************************************************
|
52
63
|
|
53
64
|
def policy
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
65
|
+
case self.method.to_sym
|
66
|
+
when :email then
|
67
|
+
:batch
|
68
|
+
when :sms then
|
69
|
+
:batch
|
70
|
+
else
|
71
|
+
:instantly
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def policy_service
|
76
|
+
if @policy_service.nil?
|
77
|
+
@policy_service = "Tolliver::Services::Policies::#{self.policy.to_s.capitalize}".constantize.new
|
78
|
+
end
|
79
|
+
@policy_service
|
62
80
|
end
|
63
81
|
|
64
82
|
# ***********************************************************************
|
@@ -67,9 +85,9 @@ module Tolliver
|
|
67
85
|
|
68
86
|
def done
|
69
87
|
if self.sent_count && self.receivers_count
|
70
|
-
|
88
|
+
self.sent_count.to_s + "/" + self.receivers_count.to_s
|
71
89
|
else
|
72
|
-
|
90
|
+
nil
|
73
91
|
end
|
74
92
|
end
|
75
93
|
|
@@ -77,34 +95,8 @@ module Tolliver
|
|
77
95
|
# Service
|
78
96
|
# ***********************************************************************
|
79
97
|
|
80
|
-
# Deliver by correct policy
|
81
98
|
def deliver
|
82
|
-
self.
|
83
|
-
end
|
84
|
-
|
85
|
-
module ClassMethods
|
86
|
-
|
87
|
-
# Deliver by correct policy
|
88
|
-
def deliver(notification_delivery_id)
|
89
|
-
|
90
|
-
# Find notification delivery object
|
91
|
-
notification_delivery = Tolliver.notification_delivery_model.find_by_id(notification_delivery_id)
|
92
|
-
return nil if notification_delivery.nil?
|
93
|
-
|
94
|
-
# "Instanly" policy
|
95
|
-
if notification_delivery.policy == :instantly
|
96
|
-
self.deliver_instantly(notification_delivery_id)
|
97
|
-
|
98
|
-
# "Batch" policy
|
99
|
-
elsif notification_delivery.policy == :batch
|
100
|
-
QC.enqueue("#{self.to_s}.deliver_batch_and_enqueue", notification_delivery_id)
|
101
|
-
else
|
102
|
-
return nil
|
103
|
-
end
|
104
|
-
|
105
|
-
return notification_delivery
|
106
|
-
end
|
107
|
-
|
99
|
+
self.policy_service.deliver(self)
|
108
100
|
end
|
109
101
|
|
110
102
|
end
|
@@ -21,54 +21,32 @@ module Tolliver
|
|
21
21
|
# *********************************************************************
|
22
22
|
|
23
23
|
belongs_to :notification_delivery, class_name: Tolliver.notification_delivery_model.to_s
|
24
|
-
belongs_to :receiver, polymorphic: true
|
25
24
|
|
26
25
|
# *********************************************************************
|
27
26
|
# Validators
|
28
27
|
# *********************************************************************
|
29
28
|
|
30
|
-
validates_presence_of :notification_delivery_id, :
|
29
|
+
validates_presence_of :notification_delivery_id, :receiver_ref, :receiver_contact
|
31
30
|
|
32
31
|
# *********************************************************************
|
33
32
|
# State
|
34
33
|
# *********************************************************************
|
35
34
|
|
36
|
-
enum_column :
|
35
|
+
enum_column :status, [
|
37
36
|
:created,
|
38
37
|
:sent,
|
39
38
|
:received,
|
40
|
-
:accepted,
|
41
39
|
:error
|
42
40
|
], default: :created
|
43
41
|
|
44
42
|
end
|
45
43
|
|
46
|
-
# ***********************************************************************
|
47
|
-
# Receiver
|
48
|
-
# ***********************************************************************
|
49
|
-
|
50
|
-
# Get name or email in case name is not set
|
51
|
-
def receiver_name_or_email
|
52
|
-
if self.receiver
|
53
|
-
if self.receiver.respond_to?(:name_formatted) && !self.receiver.name_formatted.blank?
|
54
|
-
return self.receiver.name_formatted
|
55
|
-
elsif self.receiver.respond_to?(:name) && !self.receiver.name.blank?
|
56
|
-
return self.receiver.name
|
57
|
-
else
|
58
|
-
return self.receiver.email
|
59
|
-
end
|
60
|
-
else
|
61
|
-
return nil
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
44
|
# ***********************************************************************
|
66
45
|
# Delivery
|
67
46
|
# ***********************************************************************
|
68
47
|
|
69
|
-
# Deliver notification by correct delivery kind
|
70
48
|
def deliver
|
71
|
-
|
49
|
+
self.notification_delivery.method_service.deliver(self)
|
72
50
|
end
|
73
51
|
|
74
52
|
end
|
@@ -20,19 +20,14 @@ module Tolliver
|
|
20
20
|
# Structure
|
21
21
|
# *********************************************************************
|
22
22
|
|
23
|
-
has_many :
|
23
|
+
has_many :notifications, class_name: Tolliver.notification_model.to_s, dependent: :nullify
|
24
24
|
|
25
25
|
# *********************************************************************
|
26
26
|
# Validators
|
27
27
|
# *********************************************************************
|
28
28
|
|
29
|
-
validates_presence_of :ref
|
30
|
-
|
31
|
-
# *********************************************************************
|
32
|
-
# Ref
|
33
|
-
# *********************************************************************
|
34
|
-
|
35
|
-
enum_column :ref, Tolliver.template_refs
|
29
|
+
validates_presence_of :ref, :subject
|
30
|
+
validates :ref, uniqueness: true
|
36
31
|
|
37
32
|
end
|
38
33
|
|
@@ -40,10 +35,11 @@ module Tolliver
|
|
40
35
|
|
41
36
|
def permitted_columns
|
42
37
|
[
|
38
|
+
:ref,
|
43
39
|
:subject,
|
44
40
|
:message,
|
45
|
-
:
|
46
|
-
:
|
41
|
+
:is_disabled,
|
42
|
+
:is_dry
|
47
43
|
]
|
48
44
|
end
|
49
45
|
|
@@ -9,20 +9,64 @@
|
|
9
9
|
# *
|
10
10
|
# *****************************************************************************
|
11
11
|
|
12
|
+
require 'singleton'
|
13
|
+
|
12
14
|
module Tolliver
|
13
15
|
module Services
|
14
|
-
|
15
|
-
|
16
|
+
class Delivery
|
17
|
+
include Singleton
|
18
|
+
|
19
|
+
def enqueue_for_delivery(notification)
|
20
|
+
return nil if notification.nil?
|
21
|
+
QC.enqueue("#{self.class.to_s}.deliver", notification.id)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Entry point for QC
|
25
|
+
def self.deliver(notification_id)
|
26
|
+
|
27
|
+
# Instantiate notification object
|
28
|
+
notification = Tolliver.notification_model.find_by_id(notification_id)
|
29
|
+
return nil if notification.nil?
|
30
|
+
|
31
|
+
# Call standard API
|
32
|
+
self.instance.deliver(notification)
|
33
|
+
end
|
16
34
|
|
17
|
-
|
35
|
+
# Deliver notification to receivers by all configured methods
|
36
|
+
def deliver(notification)
|
37
|
+
return nil if notification.nil?
|
18
38
|
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
39
|
+
# Load balancing
|
40
|
+
unless Tolliver.load_balance.blank?
|
41
|
+
notifications_sent_in_protected_time_window = Tolliver.notification_model
|
42
|
+
.joins(:notification_deliveries)
|
43
|
+
.where.not(id: notification.id)
|
44
|
+
.where("notification_deliveries.sent_at > ?", Time.current - Tolliver.load_balance.minutes).distinct
|
45
|
+
if notifications_sent_in_protected_time_window.count > 0
|
46
|
+
|
47
|
+
# Sleep for given amount of time
|
48
|
+
sleep(Tolliver.load_balance * 60) # seconds
|
49
|
+
|
50
|
+
# Then try again
|
51
|
+
enqueue_for_delivery(notification)
|
52
|
+
|
53
|
+
return false
|
54
|
+
end
|
24
55
|
end
|
25
56
|
|
57
|
+
# Process all notification deliveries
|
58
|
+
notification.notification_deliveries.each do |notification_delivery|
|
59
|
+
notification_delivery.policy_service.deliver(notification_delivery)
|
60
|
+
end
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def reset_delivery(notification)
|
66
|
+
return nil if notification.nil?
|
67
|
+
notification.notification_deliveries.update_all(sent_count: 0, sent_at: nil)
|
68
|
+
notification.notification_receivers.update_all(sent_at: nil, received_at: nil, status: :created, error_message: nil)
|
69
|
+
true
|
26
70
|
end
|
27
71
|
|
28
72
|
end
|