From 9f07383b0244fa0ce05238c45f27238cd3459ebf Mon Sep 17 00:00:00 2001
From: Nicholas Griffin <nicholas.griffin@bbc.co.uk>
Date: Mon, 11 Mar 2024 18:57:25 +0000
Subject: [PATCH] feat!: replacing the isRunning method with status (#459)

* feat!: replacing the isRunning method with getStatus

* chore: putting debugger back

* chore: putting test back
---
 README.md                                     | 10 ++++-
 package.json                                  |  2 +-
 src/consumer.ts                               | 15 ++++++--
 .../step_definitions/gracefulShutdown.js      |  2 +-
 .../step_definitions/handleMessage.js         | 10 ++---
 .../step_definitions/handleMessageBatch.js    | 12 ++----
 test/tests/consumer.test.ts                   | 37 ++++++++++++++++---
 7 files changed, 61 insertions(+), 27 deletions(-)

diff --git a/README.md b/README.md
index 92f77833..a3551937 100644
--- a/README.md
+++ b/README.md
@@ -125,9 +125,15 @@ By default, the value of `abort` is set to `false` which means pre existing requ
 
 `consumer.stop({ abort: true })`
 
-### `consumer.isRunning`
+### `consumer.status`
 
-Returns the current polling state of the consumer: `true` if it is actively polling, `false` if it is not.
+Returns the current status of the consumer.
+
+- `isRunning` - `true` if the consumer has been started and not stopped, `false` if was not started or if it was stopped.
+- `isPolling` - `true` if the consumer is actively polling, `false` if it is not.
+
+> **Note:**
+> This method is not available in versions before v9.0.0 and replaced the method `isRunning` to supply both running and polling states.
 
 ### `consumer.updateOption(option, value)`
 
diff --git a/package.json b/package.json
index 9e94c765..7dc5d50c 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
     "lcov": "c8 mocha && c8 report --reporter=lcov",
     "lint": "eslint . --ext .ts",
     "lint:fix": "eslint . --fix",
-    "format": "prettier --loglevel warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
+    "format": "prettier --log-level warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
     "format:check": "prettier --check \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
     "posttest": "npm run lint && npm run format:check",
     "generate-docs": "typedoc"
diff --git a/src/consumer.ts b/src/consumer.ts
index e3b962ba..8cef1022 100644
--- a/src/consumer.ts
+++ b/src/consumer.ts
@@ -56,7 +56,7 @@ export class Consumer extends TypedEventEmitter {
   private pollingWaitTimeMs: number;
   private pollingCompleteWaitTimeMs: number;
   private heartbeatInterval: number;
-  private isPolling: boolean;
+  private isPolling = false;
   private stopRequestedAtTimestamp: number;
   public abortController: AbortController;
 
@@ -174,10 +174,17 @@ export class Consumer extends TypedEventEmitter {
   }
 
   /**
-   * Returns the current polling state of the consumer: `true` if it is actively polling, `false` if it is not.
+   * Returns the current status of the consumer.
+   * This includes whether it is running or currently polling.
    */
-  public get isRunning(): boolean {
-    return !this.stopped;
+  public get status(): {
+    isRunning: boolean;
+    isPolling: boolean;
+  } {
+    return {
+      isRunning: !this.stopped,
+      isPolling: this.isPolling
+    };
   }
 
   /**
diff --git a/test/features/step_definitions/gracefulShutdown.js b/test/features/step_definitions/gracefulShutdown.js
index 8c0d52ec..00a660d2 100644
--- a/test/features/step_definitions/gracefulShutdown.js
+++ b/test/features/step_definitions/gracefulShutdown.js
@@ -31,7 +31,7 @@ Then('the application is stopped while messages are in flight', async () => {
 
   consumer.stop();
 
-  assert.strictEqual(consumer.isRunning, false);
+  assert.strictEqual(consumer.status.isRunning, false);
 });
 
 Then(
diff --git a/test/features/step_definitions/handleMessage.js b/test/features/step_definitions/handleMessage.js
index 4d5013a8..b1a2c219 100644
--- a/test/features/step_definitions/handleMessage.js
+++ b/test/features/step_definitions/handleMessage.js
@@ -26,14 +26,12 @@ Given('a message is sent to the SQS queue', async () => {
 Then('the message should be consumed without error', async () => {
   consumer.start();
 
-  const isRunning = consumer.isRunning;
-
-  assert.strictEqual(isRunning, true);
+  assert.strictEqual(consumer.status.isRunning, true);
 
   await pEvent(consumer, 'response_processed');
 
   consumer.stop();
-  assert.strictEqual(consumer.isRunning, false);
+  assert.strictEqual(consumer.status.isRunning, false);
 
   const size = await producer.queueSize();
   assert.strictEqual(size, 0);
@@ -61,7 +59,7 @@ Then(
   async () => {
     consumer.start();
 
-    assert.strictEqual(consumer.isRunning, true);
+    assert.strictEqual(consumer.status.isRunning, true);
 
     await pEvent(consumer, 'message_received');
     const size = await producer.queueSize();
@@ -82,7 +80,7 @@ Then(
 
     consumer.stop();
 
-    assert.strictEqual(consumer.isRunning, false);
+    assert.strictEqual(consumer.status.isRunning, false);
   }
 );
 
diff --git a/test/features/step_definitions/handleMessageBatch.js b/test/features/step_definitions/handleMessageBatch.js
index b51507af..9eee6ebc 100644
--- a/test/features/step_definitions/handleMessageBatch.js
+++ b/test/features/step_definitions/handleMessageBatch.js
@@ -26,14 +26,12 @@ Given('a message batch is sent to the SQS queue', async () => {
 Then('the message batch should be consumed without error', async () => {
   consumer.start();
 
-  const isRunning = consumer.isRunning;
-
-  assert.strictEqual(isRunning, true);
+  assert.strictEqual(consumer.status.isRunning, true);
 
   await pEvent(consumer, 'response_processed');
 
   consumer.stop();
-  assert.strictEqual(consumer.isRunning, false);
+  assert.strictEqual(consumer.status.isRunning, false);
 
   const size = await producer.queueSize();
   assert.strictEqual(size, 0);
@@ -61,9 +59,7 @@ Then(
   async () => {
     consumer.start();
 
-    const isRunning = consumer.isRunning;
-
-    assert.strictEqual(isRunning, true);
+    assert.strictEqual(consumer.status.isRunning, true);
 
     await pEvent(consumer, 'message_received');
 
@@ -76,7 +72,7 @@ Then(
     assert.strictEqual(size2, 0);
 
     consumer.stop();
-    assert.strictEqual(consumer.isRunning, false);
+    assert.strictEqual(consumer.status.isRunning, false);
   }
 );
 
diff --git a/test/tests/consumer.test.ts b/test/tests/consumer.test.ts
index 6fa64dbb..196771eb 100644
--- a/test/tests/consumer.test.ts
+++ b/test/tests/consumer.test.ts
@@ -1556,17 +1556,44 @@ describe('Consumer', () => {
     });
   });
 
-  describe('isRunning', async () => {
-    it('returns true if the consumer is polling', () => {
+  describe('status', async () => {
+    it('returns the defaults before the consumer is started', () => {
+      assert.isFalse(consumer.status.isRunning);
+      assert.isFalse(consumer.status.isPolling);
+    });
+
+    it('returns true for `isRunning` if the consumer has not been stopped', () => {
       consumer.start();
-      assert.isTrue(consumer.isRunning);
+      assert.isTrue(consumer.status.isRunning);
       consumer.stop();
     });
 
-    it('returns false if the consumer is not polling', () => {
+    it('returns false for `isRunning` if the consumer has been stopped', () => {
+      consumer.start();
+      consumer.stop();
+      assert.isFalse(consumer.status.isRunning);
+    });
+
+    it('returns true for `isPolling` if the consumer is polling for messages', async () => {
+      sqs.send.withArgs(mockReceiveMessage).resolves({
+        Messages: [
+          { MessageId: '1', ReceiptHandle: 'receipt-handle-1', Body: 'body-1' }
+        ]
+      });
+      consumer = new Consumer({
+        queueUrl: QUEUE_URL,
+        region: REGION,
+        handleMessage: () => new Promise((resolve) => setTimeout(resolve, 20)),
+        sqs
+      });
+
       consumer.start();
+      await Promise.all([clock.tickAsync(1)]);
+      assert.isTrue(consumer.status.isPolling);
       consumer.stop();
-      assert.isFalse(consumer.isRunning);
+      assert.isTrue(consumer.status.isPolling);
+      await Promise.all([clock.tickAsync(21)]);
+      assert.isFalse(consumer.status.isPolling);
     });
   });