ac-sqs 1.0.1
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.
- package/.acsemver.js +9 -0
- package/.eslintrc.js +27 -0
- package/CHANGELOG.md +24 -0
- package/Makefile +17 -0
- package/README.md +58 -0
- package/index.js +279 -0
- package/package.json +25 -0
package/.acsemver.js
ADDED
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
root: true,
|
|
3
|
+
'env': {
|
|
4
|
+
'commonjs': true,
|
|
5
|
+
'es6': true,
|
|
6
|
+
'node': true
|
|
7
|
+
},
|
|
8
|
+
'extends': 'eslint:recommended',
|
|
9
|
+
"rules": {
|
|
10
|
+
"space-before-function-paren": 0,
|
|
11
|
+
"no-extra-semi": 0,
|
|
12
|
+
"object-curly-spacing": ["error", "always"],
|
|
13
|
+
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
|
|
14
|
+
"no-useless-escape": 0,
|
|
15
|
+
"standard/no-callback-literal": 0,
|
|
16
|
+
"new-cap": 0
|
|
17
|
+
},
|
|
18
|
+
globals: {
|
|
19
|
+
describe: true,
|
|
20
|
+
it: true
|
|
21
|
+
},
|
|
22
|
+
'parserOptions': {
|
|
23
|
+
'ecmaVersion': 2018
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = config
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<a name="1.0.1"></a>
|
|
2
|
+
|
|
3
|
+
## [1.0.1](https://github.com/admiralcloud/ac-sanitizer/compare/v1.0.0..v1.0.1) (2021-10-09 10:38:12)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fix
|
|
7
|
+
|
|
8
|
+
* **App:** Package updates | MP | [5f79421c0a7a6c4936a02841c7c7f835d31dae3b](https://github.com/admiralcloud/ac-sanitizer/commit/5f79421c0a7a6c4936a02841c7c7f835d31dae3b)
|
|
9
|
+
Package updates
|
|
10
|
+
### Chores
|
|
11
|
+
|
|
12
|
+
* **App:** Use ac-semantic-release | MP | [f0708de0d41259c628f5012e671a73b2537c9cb9](https://github.com/admiralcloud/ac-sanitizer/commit/f0708de0d41259c628f5012e671a73b2537c9cb9)
|
|
13
|
+
Use ac-semantic-release
|
|
14
|
+
<a name="1.0.0"></a>
|
|
15
|
+
# 1.0.0 (2019-10-07 19:32)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **App:** Initial version | MP ([cdb576b](https://github.com/mmpro/ac-sqs/commit/cdb576b))
|
|
21
|
+
Initial version
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
package/Makefile
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
MOCHA_OPTS= --slow 0 -A
|
|
2
|
+
REPORTER = spec
|
|
3
|
+
|
|
4
|
+
lint-fix:
|
|
5
|
+
./node_modules/.bin/eslint --fix index.js test/test.js
|
|
6
|
+
|
|
7
|
+
lint-check:
|
|
8
|
+
./node_modules/.bin/eslint index.js test/test.js
|
|
9
|
+
|
|
10
|
+
commit:
|
|
11
|
+
@node ./node_modules/ac-semantic-release/lib/commit.js
|
|
12
|
+
|
|
13
|
+
release:
|
|
14
|
+
@node ./node_modules/ac-semantic-release/lib/release.js
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
.PHONY: check
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# AC SQS
|
|
2
|
+
This tool is a wrapper for AWS SDK's SQS function. It includes handling of big SQS messages using S3.
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
yarn add ac-sqs
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Examples
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
const acsqs = require('ac-sqs')
|
|
14
|
+
|
|
15
|
+
const sqsConfig = {
|
|
16
|
+
account: 'AWS ACCOUNT ID',
|
|
17
|
+
accessKeys: [{
|
|
18
|
+
accessKeyId: 'AWS ACCESS KEY',
|
|
19
|
+
secretAccessKey: 'AWS ACCESS SECRET',
|
|
20
|
+
default: true
|
|
21
|
+
}],
|
|
22
|
+
|
|
23
|
+
// optional if you want to use large messages
|
|
24
|
+
bucket: 'S3 bucket for large messages',
|
|
25
|
+
threshold: 250000,
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// Optional to init this tool with additional parameters
|
|
29
|
+
lists: [
|
|
30
|
+
{ name: 'playerlog', prefix: 'playerlog', processingInterval: 8000 },
|
|
31
|
+
],
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
localDevelopment: false, // if true, list will be prefixed with "local_"
|
|
35
|
+
debug: false // if true, logs will be written for every SQS call
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
acsqs.init(sqsConfig)
|
|
39
|
+
|
|
40
|
+
acsqs.listQueues({
|
|
41
|
+
prefix: 'someSQSlist'
|
|
42
|
+
}, (err, result) => {
|
|
43
|
+
console.log(23, err, result)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## ToDos
|
|
49
|
+
+ improve README
|
|
50
|
+
|
|
51
|
+
## Links
|
|
52
|
+
- [Website](https://www.admiralcloud.com/)
|
|
53
|
+
- [Twitter (@admiralcloud)](https://twitter.com/admiralcloud)
|
|
54
|
+
- [Facebook](https://www.facebook.com/MediaAssetManagement/)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
## License
|
|
58
|
+
[MIT License](https://opensource.org/licenses/MIT) Copyright © 2009-present, AdmiralCloud, Mark Poepping
|
package/index.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
const _ = require('lodash')
|
|
2
|
+
const async = require('async')
|
|
3
|
+
|
|
4
|
+
const AWS = require('aws-sdk')
|
|
5
|
+
const uuidV4 = require('uuid/v4')
|
|
6
|
+
|
|
7
|
+
const acsqs = () => {
|
|
8
|
+
|
|
9
|
+
const sqsConfig = {
|
|
10
|
+
account: '123455',
|
|
11
|
+
bucket: 'sqs.admiralcloud.com',
|
|
12
|
+
threshold: 250000,
|
|
13
|
+
lists: [
|
|
14
|
+
{ name: 'playerlog', prefix: 'playerlog', processingInterval: 8000 },
|
|
15
|
+
{ name: 'downloadlog', prefix: 'downloadlog', perCustomer: true, processingInterval: 5000 }
|
|
16
|
+
],
|
|
17
|
+
environment: process.env.NODE_ENV || 'development',
|
|
18
|
+
localDevelopment: false,
|
|
19
|
+
accessKeys: [],
|
|
20
|
+
debug: false,
|
|
21
|
+
// logger: // Winston log instance
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const init = (params) => {
|
|
25
|
+
_.forEach(params, (val, key) => {
|
|
26
|
+
if (_.has(sqsConfig, key) && val) _.set(sqsConfig, key, val)
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const generateURL = (params) => {
|
|
31
|
+
const region = _.get(params, 'region', 'eu-central-1')
|
|
32
|
+
const account = _.get(params, 'account', _.get(sqsConfig, 'account'))
|
|
33
|
+
const queueName = generateQueueName(params)
|
|
34
|
+
if (!account || !queueName) return null
|
|
35
|
+
const url = 'https://sqs.' + region + '.amazonaws.com/' + account + '/' + queueName
|
|
36
|
+
return url
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Generate the queuename based on list, fifo, env
|
|
41
|
+
*/
|
|
42
|
+
const generateQueueName = (params) => {
|
|
43
|
+
const queueName = (sqsConfig.localDevelopment ? 'local_' : '') + (sqsConfig.environment === 'test' ? 'test_' : '') + _.get(params, 'list') + (_.get(params, 'fifoQueue') ? '.fifo': '')
|
|
44
|
+
return queueName
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const callAWS = (params, cb) => {
|
|
48
|
+
const providerConfig = _.find(sqsConfig.accessKeys, { default: true })
|
|
49
|
+
const region = _.get(params, 'region', 'eu-central-1')
|
|
50
|
+
const sqs = new AWS.SQS({
|
|
51
|
+
accessKeyId: providerConfig.accessKeyId,
|
|
52
|
+
secretAccessKey: providerConfig.secretAccessKey,
|
|
53
|
+
region
|
|
54
|
+
})
|
|
55
|
+
const operation = _.get(params, 'operation')
|
|
56
|
+
const sqsParams = _.get(params, 'sqsParams')
|
|
57
|
+
if (_.get(sqsConfig, 'debug')) {
|
|
58
|
+
if (_.isFunction(sqsConfig.logger)) sqsConfig.logger.debug('ACSQS | Call %s | Payload %j', operation, sqsParams)
|
|
59
|
+
else console.log('ACSQS | Call %s | Payload %j', operation, sqsParams)
|
|
60
|
+
}
|
|
61
|
+
sqs[operation](sqsParams, cb)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const callAWSs3 = (params, cb) => {
|
|
65
|
+
const providerConfig = _.find(sqsConfig.accessKeys, { default: true })
|
|
66
|
+
const region = _.get(params, 'region', 'eu-central-1')
|
|
67
|
+
const awsS3Client = new AWS.S3({
|
|
68
|
+
accessKeyId: providerConfig.accessKeyId,
|
|
69
|
+
secretAccessKey: providerConfig.secretAccessKey,
|
|
70
|
+
region
|
|
71
|
+
})
|
|
72
|
+
const operation = _.get(params, 'operation')
|
|
73
|
+
const s3Params = _.get(params, 's3Params')
|
|
74
|
+
awsS3Client[operation](s3Params, cb)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates a new queue
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
const createQueue = (params, cb) => {
|
|
83
|
+
const sqsParams = {
|
|
84
|
+
QueueName: generateQueueName(params),
|
|
85
|
+
Attributes: {
|
|
86
|
+
VisibilityTimeout: _.get(params, 'visibilityTimeout', 60).toString(),
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (_.get(params, 'fifoQueue')) {
|
|
90
|
+
_.set(sqsParams, 'Attributes.FifoQueue', 'true')
|
|
91
|
+
}
|
|
92
|
+
if (_.get(params, 'useKMS')) {
|
|
93
|
+
_.set(sqsParams, 'Attributes.KmsMasterKeyId', _.get(params, 'kmsMasterKeyId', 'alias/aws/sqs'))
|
|
94
|
+
_.set(sqsParams, 'Attributes.KmsDataKeyReusePeriodSeconds', _.get(params, 'kmsDataKeyReusePeriodSeconds', 3600).toString())
|
|
95
|
+
}
|
|
96
|
+
if (_.get(params, 'messageRetentionPeriod')) {
|
|
97
|
+
_.set(sqsParams, 'Attributes.MessageRetentionPeriod', _.get(params, 'messageRetentionPeriod').toString())
|
|
98
|
+
}
|
|
99
|
+
callAWS({
|
|
100
|
+
operation: 'createQueue',
|
|
101
|
+
sqsParams
|
|
102
|
+
}, cb)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* List queues for a given prefix
|
|
107
|
+
*/
|
|
108
|
+
const listQueues = (params, cb) => {
|
|
109
|
+
const sqsParams = {
|
|
110
|
+
QueueNamePrefix: generateQueueName({ list: _.get(params, 'prefix') })
|
|
111
|
+
}
|
|
112
|
+
callAWS({
|
|
113
|
+
operation: 'listQueues',
|
|
114
|
+
sqsParams
|
|
115
|
+
}, cb)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get SQS list attributes
|
|
120
|
+
*
|
|
121
|
+
* @param params.list STRING List to use
|
|
122
|
+
* @param {*} cb
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
const getSQSQueueAttributes = (params, cb) => {
|
|
126
|
+
let sqsParams = {
|
|
127
|
+
QueueUrl: _.get(params, 'url', generateURL(params)),
|
|
128
|
+
AttributeNames: ['All']
|
|
129
|
+
}
|
|
130
|
+
callAWS({
|
|
131
|
+
operation: 'getQueueAttributes',
|
|
132
|
+
sqsParams
|
|
133
|
+
}, cb)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Send messages to AWS SQS
|
|
138
|
+
*
|
|
139
|
+
* @param params.list STRING List to use
|
|
140
|
+
* @param params.message STRING (string or JSON.strigify(obj))
|
|
141
|
+
* @param params.delay INT Delay in seconds
|
|
142
|
+
* @param {*} cb
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
const sendSQSMessage = (params, cb) => {
|
|
146
|
+
const list = _.get(params, 'list')
|
|
147
|
+
const additionalConfig = _.find(_.get(sqsConfig, 'lists'), { name: list })
|
|
148
|
+
if (!_.get(params, 'region') && _.get(additionalConfig, 'region')) _.set(params, 'region', _.get(additionalConfig, 'region'))
|
|
149
|
+
|
|
150
|
+
let message = params.message
|
|
151
|
+
if (!message) return cb('sendSQSMessage_message_required')
|
|
152
|
+
|
|
153
|
+
async.series({
|
|
154
|
+
messageToS3: (done) => {
|
|
155
|
+
if (message.length < _.get(sqsConfig, 'threshold')) return done()
|
|
156
|
+
// transfer message to s3 and change message
|
|
157
|
+
let s3Params = {
|
|
158
|
+
Bucket: _.get(sqsConfig, 'bucket'),
|
|
159
|
+
Key: _.get(params, 'MessageDeduplicationId', uuidV4()),
|
|
160
|
+
Body: Buffer.from(message, 'utf-8'),
|
|
161
|
+
ContentType: 'text/plain'
|
|
162
|
+
}
|
|
163
|
+
callAWSs3({
|
|
164
|
+
operation: 'putObject',
|
|
165
|
+
s3Params
|
|
166
|
+
}, (err) => {
|
|
167
|
+
if (err) return done(err)
|
|
168
|
+
message = 's3:' + _.get(s3Params, 'Key')
|
|
169
|
+
return done()
|
|
170
|
+
})
|
|
171
|
+
},
|
|
172
|
+
sendMessage: (done) => {
|
|
173
|
+
let sqsParams = {
|
|
174
|
+
MessageBody: message,
|
|
175
|
+
QueueUrl: generateURL(params)
|
|
176
|
+
}
|
|
177
|
+
if (_.get(params, 'messageGroupId')) _.set(sqsParams, 'MessageGroupId', _.get(params, 'messageGroupId'))
|
|
178
|
+
if (_.get(params, 'deDuplicationId')) _.set(sqsParams, 'MessageDeduplicationId', _.get(params, 'deDuplicationId'))
|
|
179
|
+
if (_.get(params, 'delay')) _.set(sqsParams, 'DelaySeconds', _.get(params, 'delay'))
|
|
180
|
+
callAWS({
|
|
181
|
+
operation: 'sendMessage',
|
|
182
|
+
sqsParams
|
|
183
|
+
}, done)
|
|
184
|
+
}
|
|
185
|
+
}, cb)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Receive a message from SQS
|
|
190
|
+
*/
|
|
191
|
+
const receiveSQSMessage = (params, cb) => {
|
|
192
|
+
const list = _.get(params, 'list')
|
|
193
|
+
const additionalConfig = _.find(_.get(sqsConfig, 'lists'), { name: list })
|
|
194
|
+
if (!_.get(params, 'region') && _.get(additionalConfig, 'region')) _.set(params, 'region', _.get(additionalConfig, 'region'))
|
|
195
|
+
|
|
196
|
+
let sqsParams = {
|
|
197
|
+
QueueUrl: _.get(params, 'url', generateURL(params)),
|
|
198
|
+
MaxNumberOfMessages: _.get(params, 'batchSize', _.get(additionalConfig, 'batchSize', 1)),
|
|
199
|
+
VisibilityTimeout: _.get(params, 'visibilityTimeout', _.get(additionalConfig, 'visibilityTimeout', 15))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let messages = []
|
|
203
|
+
async.series({
|
|
204
|
+
receiveMessage: (done) => {
|
|
205
|
+
callAWS({
|
|
206
|
+
operation: 'receiveMessage',
|
|
207
|
+
sqsParams
|
|
208
|
+
}, (err, result) => {
|
|
209
|
+
if (err) return done(err)
|
|
210
|
+
if (!_.size(result, 'Messages')) return done()
|
|
211
|
+
messages = _.get(result, 'Messages')
|
|
212
|
+
async.map(messages, (item, itDone) => {
|
|
213
|
+
if (!_.startsWith(_.get(item, 'Body'), 's3:')) return itDone()
|
|
214
|
+
|
|
215
|
+
let s3Params = {
|
|
216
|
+
Bucket: _.get(sqsConfig, 'bucket'),
|
|
217
|
+
Key: _.get(item, 'Body').substr(3)
|
|
218
|
+
}
|
|
219
|
+
callAWSs3({
|
|
220
|
+
operation: 'getObject',
|
|
221
|
+
s3Params
|
|
222
|
+
}, (err, result) => {
|
|
223
|
+
if (err) return itDone(err)
|
|
224
|
+
let message =_.get(result, 'Body').toString()
|
|
225
|
+
_.set(item, 'Body', message)
|
|
226
|
+
_.set(item, 's3Storage', s3Params.Key)
|
|
227
|
+
return itDone()
|
|
228
|
+
})
|
|
229
|
+
}, done)
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
}, (err) => {
|
|
233
|
+
return cb(err, messages)
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const deleteSQSMessage = (params, cb) => {
|
|
238
|
+
const list = _.get(params, 'list')
|
|
239
|
+
const additionalConfig = _.find(_.get(sqsConfig, 'lists'), { name: list })
|
|
240
|
+
if (!_.get(params, 'region') && _.get(additionalConfig, 'region')) _.set(params, 'region', _.get(additionalConfig, 'region'))
|
|
241
|
+
|
|
242
|
+
let sqsParams = {
|
|
243
|
+
QueueUrl: _.get(params, 'url', generateURL(params)),
|
|
244
|
+
ReceiptHandle: _.get(params, 'receiptHandle')
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async.series({
|
|
248
|
+
deleteMessage: (done) => {
|
|
249
|
+
callAWS({
|
|
250
|
+
operation: 'deleteMessage',
|
|
251
|
+
sqsParams
|
|
252
|
+
}, done)
|
|
253
|
+
},
|
|
254
|
+
deleteFromS3: (done) => {
|
|
255
|
+
if (!_.get(params, 's3Storage')) return done()
|
|
256
|
+
let s3Params = {
|
|
257
|
+
Bucket: _.get(sqsConfig, 'bucket'),
|
|
258
|
+
Key: _.get(params, 's3Storage')
|
|
259
|
+
}
|
|
260
|
+
callAWSs3({
|
|
261
|
+
operation: 'deleteObject',
|
|
262
|
+
s3Params
|
|
263
|
+
}, done)
|
|
264
|
+
},
|
|
265
|
+
}, cb)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return {
|
|
269
|
+
init,
|
|
270
|
+
createQueue,
|
|
271
|
+
listQueues,
|
|
272
|
+
getSQSQueueAttributes,
|
|
273
|
+
sendSQSMessage,
|
|
274
|
+
receiveSQSMessage,
|
|
275
|
+
deleteSQSMessage
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
}
|
|
279
|
+
module.exports = acsqs()
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ac-sqs",
|
|
3
|
+
"author": "Mark Poepping (https://www.admiralcloud.com)",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": "admiralcloud/ac-sqs",
|
|
6
|
+
"version": "1.0.1",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"ac-semantic-release": "^0.2.7",
|
|
9
|
+
"async": "^3.2.1",
|
|
10
|
+
"aws-sdk": "^2.1004.0",
|
|
11
|
+
"lodash": "^4.17.21",
|
|
12
|
+
"uuid": "^8.3.2"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"eslint": "^7.32.0",
|
|
16
|
+
"expect": "^27.x",
|
|
17
|
+
"mocha": "^9.x"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "mocha --reporter spec"
|
|
21
|
+
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=8.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|