Fix webhook application hang on exit

* Import d9fee18b28 manually
This commit is contained in:
abraunegg 2023-10-28 07:21:54 +11:00
parent 16595efbdb
commit 4df36ffbbe
3 changed files with 61 additions and 16 deletions

View file

@ -680,6 +680,7 @@ final class ItemDatabase {
try { try {
auto stmt = db.prepare("VACUUM;"); auto stmt = db.prepare("VACUUM;");
stmt.exec(); stmt.exec();
log.vdebug("Database vacuum is complete");
} catch (SqliteException e) { } catch (SqliteException e) {
writeln(); writeln();
log.error("ERROR: Unable to perform a database vacuum: " ~ e.msg); log.error("ERROR: Unable to perform a database vacuum: " ~ e.msg);

View file

@ -898,28 +898,33 @@ int main(string[] cliArgs) {
void performStandardExitProcess(string scopeCaller) { void performStandardExitProcess(string scopeCaller) {
// Who called this function // Who called this function
log.vdebug("Running performStandardExitProcess due to: ", scopeCaller); log.vdebug("Running performStandardExitProcess due to: ", scopeCaller);
// Shutdown the database // Wait for all parallel jobs that depend on the database to complete
if (itemDB !is null) { log.vdebug("Wait for all parallel jobs that depend on the database to complete");
// Make sure the .wal file is incorporated into the main db before we exit taskPool.finish(true);
itemDB.performVacuum();
object.destroy(itemDB);
}
// Shutdown the OneDrive API instance // Shutdown the OneDrive API instance
if (oneDriveApiInstance !is null) { if (oneDriveApiInstance !is null) {
log.vdebug("Shutdown OneDrive API instance");
oneDriveApiInstance.shutdown(); oneDriveApiInstance.shutdown();
object.destroy(oneDriveApiInstance); object.destroy(oneDriveApiInstance);
} }
// Shutdown the sync engine // Shutdown the sync engine
if (syncEngineInstance !is null) object.destroy(syncEngineInstance); if (syncEngineInstance !is null) {
log.vdebug("Shutdown Sync Engine instance");
object.destroy(syncEngineInstance);
}
// Shutdown the client side filtering objects // Shutdown the client side filtering objects
if (selectiveSync !is null) object.destroy(selectiveSync); if (selectiveSync !is null) {
log.vdebug("Shutdown Client Side Filtering instance");
object.destroy(selectiveSync);
}
// Shutdown the application configuration objects // Shutdown the application configuration objects
if (appConfig !is null) { if (appConfig !is null) {
log.vdebug("Shutdown Application Configuration instance");
// Cleanup any existing dry-run elements ... these should never be left hanging around // Cleanup any existing dry-run elements ... these should never be left hanging around
cleanupDryRunDatabaseFiles(appConfig.databaseFilePathDryRun); cleanupDryRunDatabaseFiles(appConfig.databaseFilePathDryRun);
object.destroy(appConfig); object.destroy(appConfig);
@ -927,10 +932,22 @@ void performStandardExitProcess(string scopeCaller) {
// Shutdown any local filesystem monitoring // Shutdown any local filesystem monitoring
if (filesystemMonitor !is null) { if (filesystemMonitor !is null) {
log.vdebug("Shutdown Filesystem Monitoring instance");
filesystemMonitor.shutdown(); filesystemMonitor.shutdown();
object.destroy(filesystemMonitor); object.destroy(filesystemMonitor);
} }
// Shutdown the database
if (itemDB !is null) {
log.vdebug("Shutdown Database instance");
// Make sure the .wal file is incorporated into the main db before we exit
if (itemDB.isDatabaseInitialised()) {
itemDB.performVacuum();
}
object.destroy(itemDB);
}
// Set all objects to null
if (scopeCaller == "failureScope") { if (scopeCaller == "failureScope") {
// Set these to be null due to failure scope - prevent 'ERROR: Unable to perform a database vacuum: out of memory' when the exit scope is then called // Set these to be null due to failure scope - prevent 'ERROR: Unable to perform a database vacuum: out of memory' when the exit scope is then called
log.vdebug("Setting Class Objects to null due to failure scope"); log.vdebug("Setting Class Objects to null due to failure scope");

View file

@ -76,6 +76,7 @@ class OneDriveWebhook {
private ushort port; private ushort port;
private Tid parentTid; private Tid parentTid;
private shared uint count; private shared uint count;
private bool started;
static OneDriveWebhook getOrCreate(string host, ushort port, Tid parentTid) { static OneDriveWebhook getOrCreate(string host, ushort port, Tid parentTid) {
if (!instantiated_) { if (!instantiated_) {
@ -97,9 +98,23 @@ class OneDriveWebhook {
this.parentTid = parentTid; this.parentTid = parentTid;
this.count = 0; this.count = 0;
} }
void serve() {
spawn(&serveStatic);
this.started = true;
log.log("Started webhook server");
}
void stop() {
if (this.started) {
RequestServer.stop();
this.started = false;
}
log.log("Stopped webhook server");
}
// The static serve() is necessary because spawn() does not like instance methods // The static serve() is necessary because spawn() does not like instance methods
static serve() { private static void serveStatic() {
// we won't create the singleton instance if it hasn't been created already // we won't create the singleton instance if it hasn't been created already
// such case is a bug which should crash the program and gets fixed // such case is a bug which should crash the program and gets fixed
instance_.serveImpl(); instance_.serveImpl();
@ -458,9 +473,20 @@ class OneDriveApi {
// Shutdown OneDrive API Curl Engine // Shutdown OneDrive API Curl Engine
void shutdown() { void shutdown() {
// Delete subscription if there exists any // Delete subscription if there exists any
deleteSubscription(); try {
deleteSubscription();
} catch (OneDriveException e) {
logSubscriptionError(e);
}
// Shutdown webhook server if it is running
if (webhook !is null) {
webhook.stop();
object.destroy(webhook);
}
// Reset any values to defaults, freeing any set objects // Reset any values to defaults, freeing any set objects
curlEngine.http.clearRequestHeaders(); curlEngine.http.clearRequestHeaders();
curlEngine.http.onSend = null; curlEngine.http.onSend = null;
@ -858,7 +884,7 @@ class OneDriveApi {
to!ushort(appConfig.getValueLong("webhook_listening_port")), to!ushort(appConfig.getValueLong("webhook_listening_port")),
thisTid thisTid
); );
spawn(&OneDriveWebhook.serve); webhook.serve();
} }
auto elapsed = Clock.currTime(UTC()) - subscriptionLastErrorAt; auto elapsed = Clock.currTime(UTC()) - subscriptionLastErrorAt;
@ -999,13 +1025,14 @@ class OneDriveApi {
private void deleteSubscription() { private void deleteSubscription() {
if (!hasValidSubscription()) { if (!hasValidSubscription()) {
log.vdebug("No valid Microsoft OneDrive webhook subscription to delete");
return; return;
} }
string url; string url;
url = subscriptionUrl ~ "/" ~ subscriptionId; url = subscriptionUrl ~ "/" ~ subscriptionId;
del(url); performDelete(url);
log.log("Deleted subscription"); log.vdebug("Deleted Microsoft OneDrive webhook subscription");
} }
private void logSubscriptionError(OneDriveException e) { private void logSubscriptionError(OneDriveException e) {