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 ADDED
@@ -0,0 +1,9 @@
1
+ module.exports = {
2
+ repository: {
3
+ url: 'https://github.com/admiralcloud/ac-sanitizer'
4
+ },
5
+ changelogFile: __dirname + '/CHANGELOG.md',
6
+ sections: [
7
+ { name: 'App' }
8
+ ],
9
+ }
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
+ }