From 6b3471b58ba147cb4a0a0649a4ba8fd15b7f9fa1 Mon Sep 17 00:00:00 2001
From: William Walker <wnwalker@ucsc.edu>
Date: Wed, 19 Mar 2025 17:47:07 -0700
Subject: [PATCH] feat: implement device schedule retrieval

--Implement pagination on device schedule API endpoint so that all schedules on a device within a certain window can be retrieved
--Add test
---
 .../edu/ucsc/its/temerity/core/Temerity.kt    | 27 ++++++++++++++-----
 .../ucsc/its/temerity/test/ProdReportTests.kt | 13 +++++++++
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
index 97261a2..685947d 100644
--- a/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
+++ b/temerity/src/commonMain/kotlin/edu/ucsc/its/temerity/core/Temerity.kt
@@ -596,13 +596,26 @@ public class Temerity internal constructor(
     startTime: LocalDate,
     endTime: LocalDate,
   ): List<DeviceRecordingSession> = withContext(libraryCoroutineDispatcher) {
-    val request = platformApi.getDeviceSchedule(
-      deviceId,
-      startTime.applyScheduledSessionDateFormat(),
-      endTime.applyScheduledSessionDateFormat(),
-    )
-    val response = request.executeApiResponse<String>()
-    decodeResponseCatching(response)
+    try {
+      val request = platformApi.getDeviceSchedule(
+        deviceId,
+        startTime.applyScheduledSessionDateFormat(),
+        endTime.applyScheduledSessionDateFormat(),
+      )
+      val response = request.executeApiResponse<String>()
+      return@withContext decodeResponseCatching(response)
+    } catch (e: Exception) {
+      when (e) {
+        is BreakException -> {
+          if (config.optDebugEnabled) {
+            get<KermitLogger>(named("libraryLogger")).d("Caught BreakException() from decodeResponseCatching() notifying we're done reading recording sessions from API: ${e.page} pages read")
+          }
+          return@withContext emptyList<DeviceRecordingSession>()
+        }
+
+        else -> throw e
+      }
+    }
   }
 
   public override suspend fun getStorageAnalyticsReport(groupId: Long): ByteArray = withContext(libraryCoroutineDispatcher) {
diff --git a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
index 87a5982..5f61a92 100644
--- a/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
+++ b/temerity/src/jvmTest/kotlin/edu/ucsc/its/temerity/test/ProdReportTests.kt
@@ -258,5 +258,18 @@ private class ProdReportTests : TemProdFunSpec() {
         File(saveFilename).shouldNotBeEmpty()
       }
     }
+
+    test("PlatformClient can fetch a list of courses recorded the previous day") {
+      runBlocking {
+        val yesterday = today.minus(1, DateTimeUnit.DAY)
+        val devices = testTemerity.getDevices()
+        val schedule = arrayListOf<Pair<String, List<DeviceRecordingSession>>>()
+        devices.forEach { device ->
+          val deviceDailySchedule = testTemerity.getDeviceSchedule(device.deviceId, yesterday.minus(1, DateTimeUnit.DAY), yesterday)
+          schedule.add(Pair(device.stationName, deviceDailySchedule))
+        }
+        schedule.toDataFrame().writeCSV("DeviceSchedule-$yesterday.csv")
+      }
+    }
   }
 }
-- 
GitLab