Re-expose the keep-alive flag to consumers (#22)

* Re-expose the kee-alive flag to consumers

* Update version to v3.2.0

* Attempt to reduce flakes from quick client reconnects
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5fb859..a318705 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 3.2.0
+
+- Re-expose `isInKeepAlivePeriod` flag on `SseConnection`. This flag will be
+  `true` when a connection has been dropped and is in the keep-alive period
+  waiting for a client to reconnect.
+
 ## 3.1.2
 
 - Fix an issue where the `SseClient` would not send a `done` event when there
diff --git a/lib/src/server/sse_handler.dart b/lib/src/server/sse_handler.dart
index 9c3d91e..e8cd523 100644
--- a/lib/src/server/sse_handler.dart
+++ b/lib/src/server/sse_handler.dart
@@ -37,7 +37,7 @@
   Timer _keepAliveTimer;
 
   /// Whether this connection is currently in the KeepAlive timeout period.
-  bool get _isInKeepAlivePeriod => _keepAliveTimer?.isActive ?? false;
+  bool get isInKeepAlivePeriod => _keepAliveTimer?.isActive ?? false;
 
   final _closedCompleter = Completer<void>();
 
@@ -60,7 +60,7 @@
     while (await outgoingStreamQueue.hasNext) {
       // If we're in a KeepAlive timeout, there's nowhere to send messages so
       // wait a short period and check again.
-      if (_isInKeepAlivePeriod) {
+      if (isInKeepAlivePeriod) {
         await Future.delayed(const Duration(milliseconds: 200));
         continue;
       }
@@ -105,7 +105,7 @@
     if (_keepAlive == null) {
       // Close immediately if we're not keeping alive.
       _close();
-    } else if (!_isInKeepAlivePeriod) {
+    } else if (!isInKeepAlivePeriod) {
       // Otherwise if we didn't already have an active timer, set a timer to
       // close after the timeout period. If the connection comes back, this will
       // be cancelled and all messages left in the queue tried again.
@@ -155,7 +155,7 @@
       // Check if we already have a connection for this ID that is in the process
       // of timing out (in which case we can reconnect it transparently).
       if (_connections[clientId] != null &&
-          _connections[clientId]._isInKeepAlivePeriod) {
+          _connections[clientId].isInKeepAlivePeriod) {
         _connections[clientId]._acceptReconnection(sink);
       } else {
         var connection = SseConnection(sink, keepAlive: _keepAlive);
diff --git a/pubspec.yaml b/pubspec.yaml
index 86d3c13..9e8225a 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: sse
-version: 3.1.2
+version: 3.2.0
 homepage: https://github.com/dart-lang/sse
 description: >-
   Provides client and server functionality for setting up bi-directional
diff --git a/test/sse_test.dart b/test/sse_test.dart
index 0d4040f..4f66393 100644
--- a/test/sse_test.dart
+++ b/test/sse_test.dart
@@ -179,14 +179,24 @@
 
       // Close the underlying connection.
       closeSink(connection);
-      await pumpEventQueue();
 
-      // Ensure there's still a connection.
+      // The isInKeepAlivePeriod flag may only be set for a short period because
+      // the client may connect very quickly, so only pump until it changes.
+      var maxPumps = 50;
+      while (!connection.isInKeepAlivePeriod && maxPumps-- > 0) {
+        await pumpEventQueue(times: 1);
+      }
+
+      // Ensure there's still a connection and it's marked as in the keep-alive
+      // state.
+      expect(connection.isInKeepAlivePeriod, isTrue);
       expect(handler.numberOfClients, 1);
 
-      // Ensure we can still round-trip data on the original connection.
+      // Ensure we can still round-trip data on the original connection and that
+      // the connection is no longer marked keep-alive once it's reconnected.
       connection.sink.add('bar');
       expect(await connection.stream.first, 'bar');
+      expect(connection.isInKeepAlivePeriod, isFalse);
     });
 
     test('Messages sent during disconnect arrive in-order', () async {