From 90c620042560b5edfd9d356ae4e28bea57d5d0a1 Mon Sep 17 00:00:00 2001 From: Jcomp Date: Fri, 20 Oct 2023 09:17:33 +0000 Subject: [PATCH] Add webhook support for blocking wait --- src/main.d | 84 ++++++++++++++++++++++++++++++++------------------ src/onedrive.d | 9 ++++++ 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/main.d b/src/main.d index 770403a5..afd01fb5 100644 --- a/src/main.d +++ b/src/main.d @@ -749,6 +749,7 @@ int main(string[] cliArgs) { MonoTime lastGitHubCheckTime = MonoTime.currTime(); string loopStartOutputMessage = "################################################## NEW LOOP ##################################################"; string loopStopOutputMessage = "################################################ LOOP COMPLETE ###############################################"; + bool notificationReceived = false; while (performMonitor) { // Do we need to validate the runtimeSyncDirectory to check for the presence of a '.nosync' file - the disk may have been ejected .. @@ -766,33 +767,12 @@ int main(string[] cliArgs) { } // Webhook Notification Handling - bool notificationReceived = false; // Check for notifications pushed from Microsoft to the webhook if (webhookEnabled) { // Create a subscription on the first run, or renew the subscription // on subsequent runs when it is about to expire. oneDriveApiInstance.createOrRenewSubscription(); - - // Process incoming notifications if any. - - // Empirical evidence shows that Microsoft often sends multiple - // notifications for one single change, so we need a loop to exhaust - // all signals that were queued up by the webhook. The notifications - // do not contain any actual changes, and we will always rely do the - // delta endpoint to sync to latest. Therefore, only one sync run is - // good enough to catch up for multiple notifications. - for (int signalCount = 0;; signalCount++) { - const auto signalExists = receiveTimeout(dur!"seconds"(-1), (ulong _) {}); - if (signalExists) { - notificationReceived = true; - } else { - if (notificationReceived) { - log.log("Received ", signalCount," refresh signals from the webhook"); - } - break; - } - } } // Get the current time this loop is starting @@ -926,17 +906,61 @@ int main(string[] cliArgs) { auto nextCheckTime = lastCheckTime + checkOnlineInterval; currentTime = MonoTime.currTime(); auto sleepTime = nextCheckTime - currentTime; - if(filesystemMonitor.initialised) { - // If local monitor is on - // start the worker and wait for event - if(!filesystemMonitor.isWorking()) { - workerTid.send(1); + log.vdebug("Sleep for ", sleepTime); + + if(filesystemMonitor.initialised || webhookEnabled) { + if(filesystemMonitor.initialised) { + // If local monitor is on + // start the worker and wait for event + if(!filesystemMonitor.isWorking()) { + workerTid.send(1); + } } + + if(webhookEnabled) { + // if onedrive webhook is enabled + // update sleep time based on renew interval + Duration nextWebhookCheckDuration = oneDriveApiInstance.getNextExpirationCheckDuration(); + if (nextWebhookCheckDuration < sleepTime) { + sleepTime = nextWebhookCheckDuration; + log.vdebug("Update sleeping time to ", sleepTime); + } + notificationReceived = false; + } + int res = 1; - - receiveTimeout(sleepTime, (int msg) { - res = msg; - }); + // Process incoming notifications if any. + auto signalExists = receiveTimeout(sleepTime, + (int msg) { + res = msg; + }, + (ulong _) { + notificationReceived = true; + } + ); + log.vdebug("signalExists = ", signalExists); + log.vdebug("worker status = ", res); + log.vdebug("notificationReceived = ", notificationReceived); + + // Empirical evidence shows that Microsoft often sends multiple + // notifications for one single change, so we need a loop to exhaust + // all signals that were queued up by the webhook. The notifications + // do not contain any actual changes, and we will always rely do the + // delta endpoint to sync to latest. Therefore, only one sync run is + // good enough to catch up for multiple notifications. + int signalCount = notificationReceived ? 1 : 0; + for (;; signalCount++) { + signalExists = receiveTimeout(dur!"seconds"(-1), (ulong _) {}); + if (signalExists) { + notificationReceived = true; + } else { + if (notificationReceived) { + log.log("Received ", signalCount," refresh signals from the webhook"); + } + break; + } + } + if(res == -1) { log.error("Error: Monitor worker failed."); monitorFailures = true; diff --git a/src/onedrive.d b/src/onedrive.d index 41a86488..2d6f1a45 100644 --- a/src/onedrive.d +++ b/src/onedrive.d @@ -846,6 +846,15 @@ class OneDriveApi { void resetRetryAfterValue() { retryAfterValue = 0; } + + // Return the duration to next subscriptionExpiration check + Duration getNextExpirationCheckDuration() { + SysTime now = Clock.currTime(UTC()); + if (hasValidSubscription()) + return subscriptionExpiration - now - subscriptionRenewalInterval; + else + return subscriptionRetryInterval; + } // Create a new subscription or renew the existing subscription void createOrRenewSubscription() {