Server Module Scripting

The Server Module offers a Script breakout when the client reaches finish state. In order to be called, you need to implement a onServerFinish(app) function. The app object is a ScriptApplication object that offers methods to interact with the finishing client:

class ScriptApplication {
	bool loadModuleData(moduleName, jsonObject);    // load module data into jsonObject
    bool loadBlobData(path, data, offset, size);    // load a Blob store chunk into data
    bool getBlobSize(path, size);                   // get the size of a Blob

    string onedriveSession(path);                   // create an upload session url in the users onedrive
    bool onedriveUploadChunk(session, data, offset, totalsize);
                                                    // upload a chunk to the user's onedrive
    bool onedriveCancelUpload(session);             // cancel an upload

    setProgress(progressData);                      // Report progress. The progressData Map object should
                                                    // have "total" and "completed" int members and a "message" string.
    setError(msg);                                  // Set an error message
}

The following script will load the user's PST module data, iterate through the uploaded PSTs and copy them into its Onedrive.

//
// config_server script
//

def copyBlobToOnedrive(app, file) {
    var size = 0ull;
  	var blockSize = 4 * 1024 * 1024;
  	var uploadSize;
  	var offset;
  	var data;
  
    if (!app.getBlobSize(file["blobPath"], size))  {
      app.setError("Failed to get Blob size for '" + file["blobPath"] + "'");
  	  file["status"] = "failed";
      return false;
    }
  	file["size"] = size;
  
  	var session = app.onedriveSession(file["onedrivePath"]);
  	if (session.empty()) {
      app.setError("Failed to open Onedrive Session for '" + file["onedrivePath"] + "'");
  	  file["status"] = "failed";
      return false;
    }

  	for (offset = 0ull; offset < size; offset += uploadSize) {
      	if (offset + blockSize <= size) {uploadSize = blockSize;}
      	else {uploadSize = size - offset;}

   		data = "";
      	if (!app.loadBlobData(file["blobPath"], data, offset, uploadSize)) {
          	app.setError("Failed to read chunk '" + file["blobPath"] + "' (" + to_string(offset) + ":" + to_string(uploadSize) + ")");
          	app.onedriveCancelUpload(session);
            file["status"] = "failed";
          	return false;
        }
      
      	if (!app.onedriveUploadChunk(session, data, offset, size)) {
          	gkScript.logInfo("Failed to upload chunk - retrying after sleep.");
          	gkScript.sleep(30000);
            if (app.onedriveUploadChunk(session, data, offset, size)) {
              	gkScript.logInfo("Retry succeeded.");
            } else {
                app.setError("Failed to upload chunk '" + file["onedrivePath"] + "# (" + to_string(offset) + ":" + to_string(data.size()) + "/" + to_string(size) + ")");
                app.onedriveCancelUpload(session);
                file["status"] = "failed";
                return false;
            }
        }
    }
  
  	file["status"] = "finished";
  
  	return true;
}

def onServerFinish(app) {
    var pst;
  	var moduleName = "pst";
  	var progress = ["total": 0, "completed": 0, "message": "Initializing PST copy...", "files": Map()];
  	var &files = progress["files"];
	app.setProgress(progress);

    if (!app.loadModuleData(moduleName, pst)) { return false; }

    for (c:pst["catalogs"]) {
        for (f:c.second["files"]) {
            if (f.second["state"] != 4) {
                gkScript.logError("Cannot migrate PST '" + f.first + "': not synced (" + to_string(f.second["state"]) + ")");
                continue;
            }

          	var file = Map();
          	file["blobPath"] = moduleName + f.second["remotePath"];
            file["blobSize"] = f.second["size"];
            file["blobDate"] = f.second["modified"];
          	file["onedrivePath"] = f.second["remotePath"] + "_backup";
          	files[f.first] = file;
            gkScript.logInfo("PST: " + to_json(file));
        }
    }

	progress["total"] = files.size()

	for (f:files) {
      	progress["message"] = "Copying " + f.second["blobPath"];
		app.setProgress(progress);

        if (copyBlobToOnedrive(app, f.second)) {
        	progress["completed"] += 1;
        }
    }

   	progress["message"] = "Finished PST copy.";
	app.setProgress(progress);

	return true;
}

Last updated