qdone 2.2.0 → 2.2.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.
@@ -8,9 +8,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.monitor = monitor;
10
10
  exports.interpretWildcard = interpretWildcard;
11
+ exports.getQueueAge = getQueueAge;
11
12
  exports.getAggregateData = getAggregateData;
12
13
  const sqs_js_1 = require("./sqs.js");
13
14
  const cloudWatch_js_1 = require("./cloudWatch.js");
15
+ const client_cloudwatch_1 = require("@aws-sdk/client-cloudwatch");
14
16
  const defaults_js_1 = require("./defaults.js");
15
17
  const qrlCache_js_1 = require("./qrlCache.js");
16
18
  const debug_1 = __importDefault(require("debug"));
@@ -45,16 +47,45 @@ function interpretWildcard(queueName) {
45
47
  // debug({ prefix, suffix, safeSuffix, suffixRegex })
46
48
  return { prefix, suffix, safeSuffix, suffixRegex };
47
49
  }
50
+ /**
51
+ * Gets ApproximateAgeOfOldestMessage for a single queue from CloudWatch.
52
+ * This metric is not available via the SQS GetQueueAttributes API.
53
+ */
54
+ async function getQueueAge(queueName) {
55
+ const now = new Date();
56
+ const params = {
57
+ StartTime: new Date(now.getTime() - 1000 * 60 * 5),
58
+ EndTime: now,
59
+ MetricName: 'ApproximateAgeOfOldestMessage',
60
+ Namespace: 'AWS/SQS',
61
+ Period: 300,
62
+ Dimensions: [{ Name: 'QueueName', Value: queueName }],
63
+ Statistics: ['Maximum']
64
+ };
65
+ const client = (0, cloudWatch_js_1.getCloudWatchClient)();
66
+ const cmd = new client_cloudwatch_1.GetMetricStatisticsCommand(params);
67
+ try {
68
+ const data = await client.send(cmd);
69
+ debug('getQueueAge', queueName, data);
70
+ if (!data.Datapoints || data.Datapoints.length === 0)
71
+ return 0;
72
+ return Math.max(...data.Datapoints.map(d => d.Maximum));
73
+ }
74
+ catch (e) {
75
+ debug('getQueueAge error', queueName, e);
76
+ return 0;
77
+ }
78
+ }
48
79
  /**
49
80
  * Aggregates inmportant attributes across queues and reports a summary.
50
- * Attributes:
81
+ * Attributes (from SQS GetQueueAttributes):
51
82
  * - ApproximateNumberOfMessages: Sum
52
83
  * - ApproximateNumberOfMessagesDelayed: Sum
53
84
  * - ApproximateNumberOfMessagesNotVisible: Sum
85
+ * Metrics (from CloudWatch):
54
86
  * - ApproximateAgeOfOldestMessage: Max
55
87
  */
56
88
  async function getAggregateData(queueName) {
57
- const maxAttributes = new Set(['ApproximateAgeOfOldestMessage']);
58
89
  const { prefix, suffixRegex } = interpretWildcard(queueName);
59
90
  const qrls = await (0, sqs_js_1.getMatchingQueues)(prefix, suffixRegex);
60
91
  // debug({ qrls })
@@ -68,15 +99,14 @@ async function getAggregateData(queueName) {
68
99
  const newAtrribute = parseInt(result.Attributes[key], 10);
69
100
  if (newAtrribute > 0) {
70
101
  total.contributingQueueNames.add(queue);
71
- if (maxAttributes.has(key)) {
72
- total[key] = Math.max(total[key] || 0, newAtrribute);
73
- }
74
- else {
75
- total[key] = (total[key] || 0) + newAtrribute;
76
- }
102
+ total[key] = (total[key] || 0) + newAtrribute;
77
103
  }
78
104
  }
79
105
  }
106
+ // Fetch ApproximateAgeOfOldestMessage from CloudWatch (not available via SQS API)
107
+ // Only query queues with messages to minimize CloudWatch API costs
108
+ const ageResults = await Promise.all([...total.contributingQueueNames].map(queue => getQueueAge(queue)));
109
+ total.ApproximateAgeOfOldestMessage = Math.max(0, ...ageResults);
80
110
  // debug({ total })
81
111
  // convert set to array
82
112
  total.contributingQueueNames = [...total.contributingQueueNames.values()];
@@ -61,8 +61,7 @@ async function getQueueAttributes(qrls) {
61
61
  AttributeNames: [
62
62
  'ApproximateNumberOfMessages',
63
63
  'ApproximateNumberOfMessagesNotVisible',
64
- 'ApproximateNumberOfMessagesDelayed',
65
- 'ApproximateAgeOfOldestMessage'
64
+ 'ApproximateNumberOfMessagesDelayed'
66
65
  ]
67
66
  };
68
67
  const command = new client_sqs_1.GetQueueAttributesCommand(input);
@@ -84,8 +83,7 @@ async function getQueueAttributes(qrls) {
84
83
  Attributes: {
85
84
  ApproximateNumberOfMessages: '0',
86
85
  ApproximateNumberOfMessagesNotVisible: '0',
87
- ApproximateNumberOfMessagesDelayed: '0',
88
- ApproximateAgeOfOldestMessage: '0'
86
+ ApproximateNumberOfMessagesDelayed: '0'
89
87
  }
90
88
  };
91
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qdone",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "A distributed scheduler for SQS",
5
5
  "type": "module",
6
6
  "main": "./index.js",
package/src/monitor.js CHANGED
@@ -3,7 +3,8 @@
3
3
  */
4
4
 
5
5
  import { getMatchingQueues, getQueueAttributes } from './sqs.js'
6
- import { putAggregateData } from './cloudWatch.js'
6
+ import { putAggregateData, getCloudWatchClient } from './cloudWatch.js'
7
+ import { GetMetricStatisticsCommand } from '@aws-sdk/client-cloudwatch'
7
8
  import { getOptionsWithDefaults } from './defaults.js'
8
9
  import { normalizeQueueName } from './qrlCache.js'
9
10
  import Debug from 'debug'
@@ -38,16 +39,44 @@ export function interpretWildcard (queueName) {
38
39
  return { prefix, suffix, safeSuffix, suffixRegex }
39
40
  }
40
41
 
42
+ /**
43
+ * Gets ApproximateAgeOfOldestMessage for a single queue from CloudWatch.
44
+ * This metric is not available via the SQS GetQueueAttributes API.
45
+ */
46
+ export async function getQueueAge (queueName) {
47
+ const now = new Date()
48
+ const params = {
49
+ StartTime: new Date(now.getTime() - 1000 * 60 * 5),
50
+ EndTime: now,
51
+ MetricName: 'ApproximateAgeOfOldestMessage',
52
+ Namespace: 'AWS/SQS',
53
+ Period: 300,
54
+ Dimensions: [{ Name: 'QueueName', Value: queueName }],
55
+ Statistics: ['Maximum']
56
+ }
57
+ const client = getCloudWatchClient()
58
+ const cmd = new GetMetricStatisticsCommand(params)
59
+ try {
60
+ const data = await client.send(cmd)
61
+ debug('getQueueAge', queueName, data)
62
+ if (!data.Datapoints || data.Datapoints.length === 0) return 0
63
+ return Math.max(...data.Datapoints.map(d => d.Maximum))
64
+ } catch (e) {
65
+ debug('getQueueAge error', queueName, e)
66
+ return 0
67
+ }
68
+ }
69
+
41
70
  /**
42
71
  * Aggregates inmportant attributes across queues and reports a summary.
43
- * Attributes:
72
+ * Attributes (from SQS GetQueueAttributes):
44
73
  * - ApproximateNumberOfMessages: Sum
45
74
  * - ApproximateNumberOfMessagesDelayed: Sum
46
75
  * - ApproximateNumberOfMessagesNotVisible: Sum
76
+ * Metrics (from CloudWatch):
47
77
  * - ApproximateAgeOfOldestMessage: Max
48
78
  */
49
79
  export async function getAggregateData (queueName) {
50
- const maxAttributes = new Set(['ApproximateAgeOfOldestMessage'])
51
80
  const { prefix, suffixRegex } = interpretWildcard(queueName)
52
81
  const qrls = await getMatchingQueues(prefix, suffixRegex)
53
82
  // debug({ qrls })
@@ -61,14 +90,18 @@ export async function getAggregateData (queueName) {
61
90
  const newAtrribute = parseInt(result.Attributes[key], 10)
62
91
  if (newAtrribute > 0) {
63
92
  total.contributingQueueNames.add(queue)
64
- if (maxAttributes.has(key)) {
65
- total[key] = Math.max(total[key] || 0, newAtrribute)
66
- } else {
67
- total[key] = (total[key] || 0) + newAtrribute
68
- }
93
+ total[key] = (total[key] || 0) + newAtrribute
69
94
  }
70
95
  }
71
96
  }
97
+
98
+ // Fetch ApproximateAgeOfOldestMessage from CloudWatch (not available via SQS API)
99
+ // Only query queues with messages to minimize CloudWatch API costs
100
+ const ageResults = await Promise.all(
101
+ [...total.contributingQueueNames].map(queue => getQueueAge(queue))
102
+ )
103
+ total.ApproximateAgeOfOldestMessage = Math.max(0, ...ageResults)
104
+
72
105
  // debug({ total })
73
106
  // convert set to array
74
107
  total.contributingQueueNames = [...total.contributingQueueNames.values()]
package/src/sqs.js CHANGED
@@ -55,8 +55,7 @@ export async function getQueueAttributes (qrls) {
55
55
  AttributeNames: [
56
56
  'ApproximateNumberOfMessages',
57
57
  'ApproximateNumberOfMessagesNotVisible',
58
- 'ApproximateNumberOfMessagesDelayed',
59
- 'ApproximateAgeOfOldestMessage'
58
+ 'ApproximateNumberOfMessagesDelayed'
60
59
  ]
61
60
  }
62
61
  const command = new GetQueueAttributesCommand(input)
@@ -77,8 +76,7 @@ export async function getQueueAttributes (qrls) {
77
76
  Attributes: {
78
77
  ApproximateNumberOfMessages: '0',
79
78
  ApproximateNumberOfMessagesNotVisible: '0',
80
- ApproximateNumberOfMessagesDelayed: '0',
81
- ApproximateAgeOfOldestMessage: '0'
79
+ ApproximateNumberOfMessagesDelayed: '0'
82
80
  }
83
81
  }
84
82
  }