Skip to content

Commit

Permalink
Add quota manager (ericyd#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericyd authored Mar 5, 2019
1 parent fbf3a9e commit 1da19b0
Show file tree
Hide file tree
Showing 17 changed files with 605 additions and 477 deletions.
360 changes: 190 additions & 170 deletions dist/application.gs

Large diffs are not rendered by default.

36 changes: 15 additions & 21 deletions lib/FileService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
**********************************************/

import { Util } from './Util';
import Logging from './util/Logging';
import { getMetadata } from './public';
import Properties from './Properties';
import Timer from './Timer';
import QuotaManager from './QuotaManager';
import GDriveService from './GDriveService';
import API from './API';
import MimeType from './MimeType';
Expand All @@ -14,18 +15,18 @@ import ErrorMessages from './ErrorMessages';

export default class FileService {
gDriveService: GDriveService;
timer: Timer;
quotaManager: QuotaManager;
properties: Properties;
nativeMimeTypes: string[];
maxNumberOfAttempts: number;

constructor(
gDriveService: GDriveService,
timer: Timer,
quotaManager: QuotaManager,
properties: Properties
) {
this.gDriveService = gDriveService;
this.timer = timer;
this.quotaManager = quotaManager;
this.properties = properties;
this.nativeMimeTypes = [
MimeType.DOC,
Expand Down Expand Up @@ -85,7 +86,7 @@ export default class FileService {
try {
permissions = this.gDriveService.getPermissions(srcId).items;
} catch (e) {
Util.log({ status: Util.composeErrorMsg(e) });
Logging.log({ status: Util.composeErrorMsg(e) });
}

// copy editors, viewers, and commenters from src file to dest file
Expand Down Expand Up @@ -149,7 +150,7 @@ export default class FileService {
try {
destPermissions = this.gDriveService.getPermissions(destId).items;
} catch (e) {
Util.log({ status: Util.composeErrorMsg(e) });
Logging.log({ status: Util.composeErrorMsg(e) });
}

if (destPermissions && destPermissions.length > 0) {
Expand All @@ -176,23 +177,17 @@ export default class FileService {
* Destination folder must be set to the parent of the first leftover item.
* The list of leftover items is an equivalent array to fileList returned from the getFiles() query
*/
handleLeftovers(
userProperties: GoogleAppsScript.Properties.UserProperties,
ss: GoogleAppsScript.Spreadsheet.Sheet
): void {
handleLeftovers(ss: GoogleAppsScript.Spreadsheet.Sheet): void {
if (Util.hasSome(this.properties.leftovers, 'items')) {
this.properties.currFolderId = this.properties.leftovers.items[0].parents[0].id;
this.processFileList(this.properties.leftovers.items, userProperties, ss);
this.processFileList(this.properties.leftovers.items, ss);
}
}

handleRetries(
userProperties: GoogleAppsScript.Properties.UserProperties,
ss: GoogleAppsScript.Spreadsheet.Sheet
): void {
handleRetries(ss: GoogleAppsScript.Spreadsheet.Sheet): void {
if (Util.hasSome(this.properties, 'retryQueue')) {
this.properties.currFolderId = this.properties.retryQueue[0].parents[0].id;
this.processFileList(this.properties.retryQueue, userProperties, ss);
this.processFileList(this.properties.retryQueue, ss);
}
}

Expand All @@ -205,25 +200,24 @@ export default class FileService {
*/
processFileList(
items: gapi.client.drive.FileResource[],
userProperties: GoogleAppsScript.Properties.UserProperties,
ss: GoogleAppsScript.Spreadsheet.Sheet
): void {
while (items.length > 0 && this.timer.canContinue()) {
while (items.length > 0 && this.quotaManager.canContinue()) {
// Get next file from passed file list.
var item = items.pop();

if (
item.numberOfAttempts &&
item.numberOfAttempts > this.maxNumberOfAttempts
) {
Util.logCopyError(ss, item.error, item, this.properties.timeZone);
Logging.logCopyError(ss, item.error, item, this.properties.timeZone);
continue;
}

// Copy each (files and folders are both represented the same in Google Drive)
try {
var newfile = this.copyFile(item);
Util.logCopySuccess(ss, newfile, this.properties.timeZone);
Logging.logCopySuccess(ss, newfile, this.properties.timeZone);
} catch (e) {
this.properties.retryQueue.unshift({
id: item.id,
Expand Down Expand Up @@ -252,7 +246,7 @@ export default class FileService {
}

// Update current runtime and user stop flag
this.timer.update(userProperties);
this.quotaManager.update;
}
}

Expand Down
25 changes: 25 additions & 0 deletions lib/QuotaManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Timer from './Timer';

export default class QuotaManager {
timer: Timer;
userProperties: GoogleAppsScript.Properties.UserProperties;
stop: boolean;

constructor(
timer: Timer,
userProperties: GoogleAppsScript.Properties.UserProperties
) {
this.timer = timer;
this.userProperties = userProperties;
this.stop = false;
}

update() {
this.timer.update();
this.stop = this.userProperties.getProperty('stop') == 'true';
}

canContinue(): boolean {
return this.timer.canContinue() && !this.stop;
}
}
15 changes: 6 additions & 9 deletions lib/Timer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,40 @@ export default class Timer {
static MAX_RUNTIME_PER_DAY: number = 88 * 1000 * 60;
static MAX_RUNTIME: number = 4.7 * 1000 * 60;
// durations used for setting Triggers
static oneDay: number = 24 * 60 * 60 * 1000;
static sixMinutes: number = 6.2 * 1000 * 60;
static ONE_DAY: number = 24 * 60 * 60 * 1000;
static SIX_MINUTES: number = 6.2 * 1000 * 60;

START_TIME: number;
runtime: number;
timeIsUp: boolean;
stop: boolean;

constructor() {
this.START_TIME = new Date().getTime();
this.runtime = 0;
this.timeIsUp = false;
this.stop = false;

return this;
}

/**
* Update current time
*/
update(userProperties: GoogleAppsScript.Properties.UserProperties): void {
update(): void {
this.runtime = Timer.now() - this.START_TIME;
this.timeIsUp = this.runtime >= Timer.MAX_RUNTIME;
this.stop = userProperties.getProperty('stop') == 'true';
}

canContinue(): boolean {
return !this.timeIsUp && !this.stop;
return !this.timeIsUp;
}

/**
* Calculate how far in the future the trigger should be set
*/
calculateTriggerDuration(properties: Properties): number {
return properties.checkMaxRuntime()
? Timer.oneDay
: Timer.sixMinutes - this.runtime;
? Timer.ONE_DAY
: Timer.SIX_MINUTES - this.runtime;
}

static now(): number {
Expand Down
5 changes: 3 additions & 2 deletions lib/TriggerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { Util } from './Util';
import Timer from './Timer';
import Logging from './util/Logging';

export default class TriggerService {
/**
Expand All @@ -13,7 +14,7 @@ export default class TriggerService {
static createTrigger(duration: number): void {
// default is 6.2 minutes from now
// Timer will stop execution after 4.7 minutes, so this gives about 1.5 minutes buffer
duration = duration || Timer.sixMinutes;
duration = duration || Timer.SIX_MINUTES;
var trigger = ScriptApp.newTrigger('copy')
.timeBased()
.after(duration)
Expand Down Expand Up @@ -46,7 +47,7 @@ export default class TriggerService {
}
}
} catch (e) {
Util.log({ status: Util.composeErrorMsg(e) });
Logging.log({ status: Util.composeErrorMsg(e) });
}
}
}
Expand Down
Loading

0 comments on commit 1da19b0

Please sign in to comment.