Skip to content

Commit

Permalink
Make OneDriveWebhook a Singleton class
Browse files Browse the repository at this point in the history
  • Loading branch information
Lyncredible committed Nov 23, 2021
1 parent 2a424a8 commit 5b89455
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ int main(string[] args)

// Do we configure to disable the upload validation routine
if (cfg.getValueBool("disable_upload_validation")) sync.setDisableUploadValidation();

// Do we configure to disable the download validation routine
if (cfg.getValueBool("disable_download_validation")) sync.setDisableDownloadValidation();

Expand Down Expand Up @@ -1135,7 +1135,7 @@ int main(string[] args)
// 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 _) => {});
const auto signalExists = receiveTimeout(dur!"seconds"(-1), (ulong _) {});
if (signalExists) {
notificationReceived = true;
} else {
Expand Down
65 changes: 53 additions & 12 deletions src/onedrive.d
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,68 @@ class OneDriveException: Exception
}
}

shared class OneDriveWebhook {
class OneDriveWebhook {
// We need OneDriveWebhook.serve to be a static function, otherwise we would hit the member function
// "requires a dual-context, which is deprecated" warning. The root cause is described here:
// - https://issues.dlang.org/show_bug.cgi?id=5710
// - https://forum.dlang.org/post/[email protected]
// The problem is deemed a bug and should be fixed in the compilers eventually. The singleton stuff
// could be undone when it is fixed.
//
// Following the singleton pattern described here: https://wiki.dlang.org/Low-Lock_Singleton_Pattern
// Cache instantiation flag in thread-local bool
// Thread local
private static bool instantiated_;

// Thread global
private __gshared OneDriveWebhook instance_;

private string host;
private ushort port;
private uint count;
private Tid parentTid;
private shared uint count;

static OneDriveWebhook getOrCreate(string host, ushort port, Tid parentTid) {
if (!instantiated_) {
synchronized(OneDriveWebhook.classinfo) {
if (!instance_) {
instance_ = new OneDriveWebhook(host, port, parentTid);
}

instantiated_ = true;
}
}

this(string host, ushort port) {
return instance_;
}

private this(string host, ushort port, Tid parentTid) {
this.host = host;
this.port = port;
this.parentTid = parentTid;
this.count = 0;
}

// The static serve() is necessary because spawn() does not like instance methods
static serve(shared OneDriveWebhook webhook, Tid parentTid) {
webhook.serve(parentTid);
static serve() {
// 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
instance_.serveImpl();
}

// The static handle() is necessary to work around the dual-context warning mentioned above
private static void handle(Cgi cgi) {
// 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
instance_.handleImpl(cgi);
}

private void serve(Tid parentTid) {
private void serveImpl() {
auto server = new RequestServer(host, port);
server.serveEmbeddedHttp!(cgi => handle(cgi, parentTid))();
server.serveEmbeddedHttp!handle();
}

private void handle(Cgi cgi, Tid parentTid) {
private void handleImpl(Cgi cgi) {
if (.debugResponse) {
log.log("Webhook request: ", cgi.requestMethod, " ", cgi.requestUri);
if (!cgi.postBody.empty) {
Expand Down Expand Up @@ -159,7 +199,7 @@ final class OneDriveApi
private string refreshToken, accessToken, subscriptionId;
private SysTime accessTokenExpiration;
private HTTP http;
private shared OneDriveWebhook webhook;
private OneDriveWebhook webhook;
private SysTime subscriptionExpiration;
private Duration subscriptionExpirationInterval, subscriptionRenewalInterval;
private string notificationUrl;
Expand Down Expand Up @@ -910,11 +950,12 @@ final class OneDriveApi

// Kick off the webhook server first
if (webhook is null) {
webhook = new shared OneDriveWebhook(
webhook = OneDriveWebhook.getOrCreate(
cfg.getValueString("webhook_listening_host"),
to!ushort(cfg.getValueLong("webhook_listening_port"))
to!ushort(cfg.getValueLong("webhook_listening_port")),
thisTid
);
spawn(&OneDriveWebhook.serve, webhook, thisTid);
spawn(&OneDriveWebhook.serve);
}

if (!hasValidSubscription()) {
Expand Down

0 comments on commit 5b89455

Please sign in to comment.