Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
253 lines (229 loc) · 7.89 KB
/
Copy pathindex.js
File metadata and controls
253 lines (229 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
'use strict'
let amqp
let rabbitqueue
let exchangeName
let queueName
let deliveryMode
let connExchange_
let connQueue_
let routing_
exports.register = function () {
this.load_rabbitmq_ini()
if (this.cfg.main.module === 'amqp') {
exports.exchangeMapping = {}
amqp = require('amqp')
this.logdebug('About to connect and initialize queue object')
this.init_rabbitmq_server()
this.register_hook('queue', 'amqp_queue')
this.logdebug(
`Finished initiating : ${exports.exchangeMapping[exchangeName + queueName]}`,
)
} else if (this.cfg.main.module === 'amqplib') {
amqp = require('amqplib/callback_api')
this.init_amqp_connection()
}
}
exports.load_rabbitmq_ini = function () {
this.cfg = this.config.get(
'rabbitmq.ini',
{
booleans: [
'+rabbitmq.confirm',
'+rabbitmq.durable',
'-rabbitmq.autoDelete',
'+amqplib.confirm',
'+amqplib.durable',
'-amqplib.autoDelete',
],
},
() => {
this.load_rabbitmq_ini()
},
)
}
//Actual magic of publishing message to rabbit when email comes happen here.
exports.amqp_queue = function (next, connection) {
if (!connection?.transaction) return next()
//Calling the get_data method and when it gets the data on callback, publish the message to queue with routing key.
connection.transaction.message_stream.get_data((buffere) => {
const exchangeData = exports.exchangeMapping[exchangeName + queueName]
this.logdebug(
`Sending the data: ${queueName} Routing : ${exchangeData} exchange :${connExchange_}`,
)
if (connExchange_ && routing_) {
//This is publish function of rabbitmq amqp library, currently direct queue is configured and routing is fixed.
//Needs to be changed.
connExchange_.publish(routing_, buffere, { deliveryMode }, (error) => {
if (error) {
//There was some error while sending the email to queue.
this.logdebug(`queueFailure: ${JSON.stringify(error)}`)
this.init_rabbitmq_server()
next()
} else {
//Queueing was successful, send ok as reply
this.logdebug('queueSuccess')
next(OK, 'Successfully Queued! in rabbitmq')
}
})
} else {
//Seems like connExchange is not defined, lets create one for next call
this.init_rabbitmq_server()
next()
}
})
}
//This initializes the connection to rabbitmq server, It reads values from rabbitmq.ini file in config directory.
exports.init_rabbitmq_server = function () {
// this is called during init of rabbitmq
const confirm = this.cfg.rabbitmq?.confirm ?? true
const durable = this.cfg.rabbitmq?.durable ?? true
const autoDelete = this.cfg.rabbitmq?.autoDelete ?? false
const exchangeType = this.cfg.rabbitmq?.exchangeType || 'direct'
queueName = this.cfg.rabbitmq?.queueName || 'emails'
exchangeName = this.cfg.rabbitmq?.exchangeName || 'emailMessages'
deliveryMode = this.cfg.rabbitmq?.deliveryMode ?? 2
this.logdebug('Creating connection with server')
rabbitqueue = amqp.createConnection({
host: this.cfg.rabbitmq.server_ip || '127.0.0.1',
port: this.cfg.rabbitmq.server_port || '5672',
login: this.cfg.rabbitmq.user || 'guest',
password: this.cfg.rabbitmq.password || 'guest',
})
//Declaring listener on error on connection.
rabbitqueue.on('error', (error) => {
this.logerror(`There was some error on the connection : ${error}`)
})
//Declaring listerner on close on connection.
rabbitqueue.on('close', (close) => {
this.logdebug(` Connection is being closed : ${close}`)
})
/* Declaring the function to perform when connection is established and ready, function involves like:
* 1. Creating or connecting to Exchange.
* 2. Creating or connecting to Queue.
* 3. Binding the Exchange and Queue.
* 4. Saving some variables in global to be used while publishing message.
*/
rabbitqueue.on('ready', () => {
this.logdebug('Connection is ready, will try making exchange')
// Now connection is ready will try to open exchange with config data.
rabbitqueue.exchange(
exchangeName,
{ type: exchangeType, confirm, durable },
(connExchange) => {
this.logdebug(
`connExchange with server ${connExchange} autoDelete : ${autoDelete}`,
)
//Exchange is now open, will try to open queue.
return rabbitqueue.queue(
queueName,
{ autoDelete, durable },
(connQueue) => {
this.logdebug(`connQueue with server ${connQueue}`)
//Creating the Routing key to bind the queue and exchange.
const routing = `${queueName}Routing`
// Will try to bing queue and exchange which was created above.
connQueue.bind(connExchange, routing)
const key = exchangeName + queueName
//Save the variables for publising later.
if (!exports.exchangeMapping[key]) {
exports.exchangeMapping[key] = []
}
connExchange_ = connExchange
connQueue_ = connQueue
routing_ = routing
exports.exchangeMapping[key].push({
exchange: connExchange_,
queue: connQueue_,
routing: routing_,
queueName,
})
this.logdebug(
`exchange: ${exchangeName}, queue: ${queueName} exchange : ${connExchange_} queue : ${connQueue_}`,
)
},
)
},
)
})
}
let channel
let queue
let priority
exports.rabbitmq_queue = function (next, connection) {
if (!connection?.transaction) return next()
connection.transaction.message_stream.get_data((str) => {
const sendOptions = { deliveryMode }
if (priority != null) {
sendOptions.priority = priority
}
if (channel?.sendToQueue(queue, str, sendOptions)) {
return next(OK)
} else {
this.logerror('Failed to queue to rabbitmq')
return next()
}
})
}
exports.init_amqp_connection = function () {
const cfg = this.config.get('rabbitmq.ini').amqplib
const protocol = cfg.protocol || 'amqp'
const host = cfg.host || '127.0.0.1'
const port = cfg.port || '5672'
const vhost = cfg.vhost || ''
const user = encodeURIComponent(cfg.user || 'guest')
const password = encodeURIComponent(cfg.password || 'guest')
const exchangeName = cfg.exchangeName || 'emailMessages'
const exchangeType = cfg.exchangeType || 'direct'
const queueName = cfg.queueName || 'emails'
const durable = cfg.durable ?? true
const autoDelete = cfg.autoDelete ?? false
deliveryMode = cfg.deliveryMode || 2
priority = cfg.priority
amqp.connect(
`${protocol}://${user}:${password}@${host}:${port}${vhost}`,
(err, conn) => {
if (err) {
this.logerror(`Connection to rabbitmq failed: ${err}`)
return
}
// TODO: if !confirm conn.createChannel...
conn.createConfirmChannel((err2, ch) => {
if (err2) {
this.logerror(`Error creating rabbitmq channel: ${err2}`)
return conn.close()
}
ch.assertExchange(
exchangeName,
exchangeType,
{
durable,
arguments: this.cfg.exchange_args,
},
(err3) => {
if (err3) {
this.logerror(`Error asserting rabbitmq exchange: ${err3}`)
return conn.close()
}
ch.assertQueue(
queueName,
{
durable,
autoDelete,
arguments: this.cfg.amqplib_args,
},
(err4, ok2) => {
if (err4) {
this.logerror(`Error asserting rabbitmq queue: ${err4}`)
return conn.close()
}
queue = ok2.queue
channel = ch
this.register_hook('queue', 'rabbitmq_queue')
},
)
},
)
})
},
)
}