Repository: Accenture/sfmc-devtools (js)

Issue:
[BUG] rate limit automation retrieval
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

even with few automations found, we are running too many calls in parallel as there is no throttling implemented for this so far:

![image](https://github.com/Accenture/sfmc-devtools/assets/1917227/4f8db44e-0cf3-4d82-bb85-bf80989e6696)


### Expected Behavior

we should limit the amount of parallel requests as done for assets and other types

### Steps To Reproduce

_No response_

### Version

5.1.0

### Environment

_No response_

### Participation

- [X] I am willing to submit a pull request for this issue.

### Additional comments

_No response_

Pull request description:
Bugfix/1048 rate limit automation retrieval & improve automation schedule documentation
# PR details

## What changes did you make? (Give an overview)

- closes #1048 



## Checklist

- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] test scripts updated
- [ ] Wiki updated (if applicable)


Patch:
diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js
index 119681b0..ec2bcc3e 100644
--- a/lib/metadataTypes/Automation.js
+++ b/lib/metadataTypes/Automation.js
@@ -47,31 +47,36 @@ class Automation extends MetadataType {
                 )
             );
         }
+        // the API seems to handle 100 concurrent requests nicely
+        const rateLimit = pLimit(100);
+
         const details = results.Results
             ? await Promise.all(
-                  results.Results.map(async (a) => {
-                      try {
-                          return await this.client.rest.get(
-                              '/automation/v1/automations/' + a.ObjectID
-                          );
-                      } catch (ex) {
+                  results.Results.map(async (item) =>
+                      rateLimit(async () => {
                           try {
-                              if (ex.message == 'socket hang up') {
-                                  // one more retry; it's a rare case but retrying again should solve the issue gracefully
-                                  return await this.client.rest.get(
-                                      '/automation/v1/automations/' + a.ObjectID
-                                  );
+                              return await this.client.rest.get(
+                                  '/automation/v1/automations/' + item.ObjectID
+                              );
+                          } catch (ex) {
+                              try {
+                                  if (ex.message == 'socket hang up') {
+                                      // one more retry; it's a rare case but retrying again should solve the issue gracefully
+                                      return await this.client.rest.get(
+                                          '/automation/v1/automations/' + item.ObjectID
+                                      );
+                                  }
+                              } catch {
+                                  // no extra action needed, handled below
                               }
-                          } catch {
-                              // no extra action needed, handled below
+                              // if we do get here, we should log the error and continue instead of failing to download all automations
+                              Util.logger.error(
+                                  ` ☇ skipping Automation ${item.ObjectID}: ${ex.message} ${ex.code}`
+                              );
+                              return null;
                           }
-                          // if we do get here, we should log the error and continue instead of failing to download all automations
-                          Util.logger.error(
-                              ` ☇ skipping Automation ${a.ObjectID}: ${ex.message} ${ex.code}`
-                          );
-                          return null;
-                      }
-                  })
+                      })
+                  )
               )
             : [];
 
@@ -1323,9 +1328,20 @@ class Automation extends MetadataType {
                 }
                 const frequency = ical.FREQ.slice(0, -2).toLowerCase();
 
-                output += `* Recurrance: every ${ical.INTERVAL > 1 ? ical.INTERVAL : ''} ${
-                    frequency === 'dai' ? 'day' : frequency
-                }${ical.INTERVAL > 1 ? 's' : ''}${ical.COUNT ? ` for ${ical.COUNT} times` : ''}\n`;
+                output += `* Recurrance: `;
+                output +=
+                    ical.COUNT == 1
+                        ? 'run only once'
+                        : `every${ical.INTERVAL > 1 ? ' ' + ical.INTERVAL : ''} ${
+                              frequency === 'dai' ? 'day' : frequency
+                          }${ical.INTERVAL > 1 ? 's' : ''}${
+                              ical.COUNT
+                                  ? ` for ${ical.COUNT} times`
+                                  : ical.UNTIL
+                                  ? ' until end date'
+                                  : ''
+                          }`;
+                output += '\n';
             } else if (json.schedule) {
                 output += `**Schedule:** Not defined\n`;
             }


Test patch:
diff --git a/test/resources/9999999/automation/create-testNew_automation-expected.md b/test/resources/9999999/automation/create-testNew_automation-expected.md
index c607175c..ce52ff45 100644
--- a/test/resources/9999999/automation/create-testNew_automation-expected.md
+++ b/test/resources/9999999/automation/create-testNew_automation-expected.md
@@ -13,7 +13,7 @@
 * Start: 2020-05-13 18:30:32.11-06:00 +01:00
 * End: 2079-06-06 21:00:00-06:00 +01:00
 * Timezone: W. Europe Standard Time
-* Recurrance: every 5 minutes
+* Recurrance: every 5 minutes until end date
 
 **Notifications:** _none_
 
diff --git a/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md b/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md
index ae8f4c10..6c22b1c5 100644
--- a/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md
+++ b/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md
@@ -13,7 +13,7 @@
 * Start: 2022-07-30 00:00:00 +01:00
 * End: 2022-07-30 00:00:00 +01:00
 * Timezone: W. Europe Standard Time
-* Recurrance: every  day for 1 times
+* Recurrance: run only once
 
 **Notifications:**
 
diff --git a/test/resources/9999999/automation/update-testExisting_automation-expected.md b/test/resources/9999999/automation/update-testExisting_automation-expected.md
index fbee3558..fb007b2d 100644
--- a/test/resources/9999999/automation/update-testExisting_automation-expected.md
+++ b/test/resources/9999999/automation/update-testExisting_automation-expected.md
@@ -13,7 +13,7 @@
 * Start: 2022-07-30 00:00:00 +01:00
 * End: 2022-07-30 00:00:00 +01:00
 * Timezone: W. Europe Standard Time
-* Recurrance: every  day for 1 times
+* Recurrance: run only once
 
 **Notifications:** _none_