Bug 1344743 - Update TelemetryStorage.jsm to async function & await. r?Dexter draft
authorSubhdeep Saha <subhdeepsaha@gmail.com>
Fri, 10 Mar 2017 14:59:49 +0530
changeset 502061 088dac207adfa12740aa6ce01ab65821215e765a
parent 499907 dd2f2db1f87aa31e98d204a707dcfd6457a6c696
child 550045 c799bc44dc8c994c2e02cca41bd6e6ae5c623398
push id50162
push userbmo:subhdeepsaha@gmail.com
push dateTue, 21 Mar 2017 06:55:25 +0000
reviewersDexter
bugs1344743
milestone55.0a1
Bug 1344743 - Update TelemetryStorage.jsm to async function & await. r?Dexter MozReview-Commit-ID: 7stlyHefdbr
toolkit/components/telemetry/TelemetryStorage.jsm
--- a/toolkit/components/telemetry/TelemetryStorage.jsm
+++ b/toolkit/components/telemetry/TelemetryStorage.jsm
@@ -414,19 +414,19 @@ this.TelemetryStorage = {
   },
 
   /**
    * Loads a ping file.
    * @param {String} aFilePath The path of the ping file.
    * @return {Promise<Object>} A promise resolved with the ping content or rejected if the
    *                           ping contains invalid data.
    */
-  loadPingFile: Task.async(function* (aFilePath) {
+  async loadPingFile(aFilePath) {
     return TelemetryStorageImpl.loadPingFile(aFilePath);
-  }),
+  },
 
   /**
    * Remove FHR database files. This is temporary and will be dropped in
    * the future.
    * @return {Promise} Resolved when the database files are deleted.
    */
   removeFHRDatabase() {
     return TelemetryStorageImpl.removeFHRDatabase();
@@ -600,210 +600,210 @@ var TelemetryStorageImpl = {
     return this._logger;
   },
 
   /**
    * Shutdown & block on any outstanding async activity in this module.
    *
    * @return {Promise} Promise that is resolved when shutdown is complete.
    */
-  shutdown: Task.async(function*() {
+  async shutdown() {
     this._shutdown = true;
 
     // If the following tasks are still running, block on them. They will bail out as soon
     // as possible.
-    yield this._abortedSessionSerializer.flushTasks().catch(ex => {
+    await this._abortedSessionSerializer.flushTasks().catch(ex => {
       this._log.error("shutdown - failed to flush aborted-session writes", ex);
     });
 
-    yield this._deletionPingSerializer.flushTasks().catch(ex => {
+    await this._deletionPingSerializer.flushTasks().catch(ex => {
       this._log.error("shutdown - failed to flush deletion ping writes", ex);
     });
 
     if (this._cleanArchiveTask) {
-      yield this._cleanArchiveTask.catch(ex => {
+      await this._cleanArchiveTask.catch(ex => {
         this._log.error("shutdown - the archive cleaning task failed", ex);
       });
     }
 
     if (this._enforcePendingPingsQuotaTask) {
-      yield this._enforcePendingPingsQuotaTask.catch(ex => {
+      await this._enforcePendingPingsQuotaTask.catch(ex => {
         this._log.error("shutdown - the pending pings quota task failed", ex);
       });
     }
 
     if (this._removePendingPingsTask) {
-      yield this._removePendingPingsTask.catch(ex => {
+      await this._removePendingPingsTask.catch(ex => {
         this._log.error("shutdown - the pending pings removal task failed", ex);
       });
     }
 
     // Wait on pending pings still being saved. While OS.File should have shutdown
     // blockers in place, we a) have seen weird errors being reported that might
     // indicate a bad shutdown path and b) might have completion handlers hanging
     // off the save operations that don't expect to be late in shutdown.
-    yield this.promisePendingPingSaves();
-  }),
+    await this.promisePendingPingSaves();
+  },
 
   /**
    * Save an archived ping to disk.
    *
    * @param {object} ping The ping data to archive.
    * @return {promise} Promise that is resolved when the ping is successfully archived.
    */
   saveArchivedPing(ping) {
     let promise = this._saveArchivedPingTask(ping);
     this._activelyArchiving.add(promise);
     promise.then((r) => { this._activelyArchiving.delete(promise); },
                  (e) => { this._activelyArchiving.delete(promise); });
     return promise;
   },
 
-  _saveArchivedPingTask: Task.async(function*(ping) {
+  async _saveArchivedPingTask(ping) {
     const creationDate = new Date(ping.creationDate);
     if (this._archivedPings.has(ping.id)) {
       const data = this._archivedPings.get(ping.id);
       if (data.timestampCreated > creationDate.getTime()) {
         this._log.error("saveArchivedPing - trying to overwrite newer ping with the same id");
         return Promise.reject(new Error("trying to overwrite newer ping with the same id"));
       }
       this._log.warn("saveArchivedPing - overwriting older ping with the same id");
     }
 
     // Get the archived ping path and append the lz4 suffix to it (so we have 'jsonlz4').
     const filePath = getArchivedPingPath(ping.id, creationDate, ping.type) + "lz4";
-    yield OS.File.makeDir(OS.Path.dirname(filePath), { ignoreExisting: true,
+    await OS.File.makeDir(OS.Path.dirname(filePath), { ignoreExisting: true,
                                                        from: OS.Constants.Path.profileDir });
-    yield this.savePingToFile(ping, filePath, /* overwrite*/ true, /* compressed*/ true);
+    await this.savePingToFile(ping, filePath, /* overwrite*/ true, /* compressed*/ true);
 
     this._archivedPings.set(ping.id, {
       timestampCreated: creationDate.getTime(),
       type: internString(ping.type),
     });
 
     Telemetry.getHistogramById("TELEMETRY_ARCHIVE_SESSION_PING_COUNT").add();
     return undefined;
-  }),
+  },
 
   /**
    * Load an archived ping from disk.
    *
    * @param {string} id The pings id.
    * @return {promise<object>} Promise that is resolved with the ping data.
    */
-  loadArchivedPing: Task.async(function*(id) {
+  async loadArchivedPing(id) {
     const data = this._archivedPings.get(id);
     if (!data) {
       this._log.trace("loadArchivedPing - no ping with id: " + id);
       return Promise.reject(new Error("TelemetryStorage.loadArchivedPing - no ping with id " + id));
     }
 
     const path = getArchivedPingPath(id, new Date(data.timestampCreated), data.type);
     const pathCompressed = path + "lz4";
 
     // Purge pings which are too big.
-    let checkSize = function*(path) {
-      const fileSize = (yield OS.File.stat(path)).size;
+    let checkSize = async function(path) {
+      const fileSize = (await OS.File.stat(path)).size;
       if (fileSize > PING_FILE_MAXIMUM_SIZE_BYTES) {
         Telemetry.getHistogramById("TELEMETRY_DISCARDED_ARCHIVED_PINGS_SIZE_MB")
                  .add(Math.floor(fileSize / 1024 / 1024));
         Telemetry.getHistogramById("TELEMETRY_PING_SIZE_EXCEEDED_ARCHIVED").add();
-        yield OS.File.remove(path, {ignoreAbsent: true});
+        await OS.File.remove(path, {ignoreAbsent: true});
         throw new Error("loadArchivedPing - exceeded the maximum ping size: " + fileSize);
       }
     };
 
     try {
       // Try to load a compressed version of the archived ping first.
       this._log.trace("loadArchivedPing - loading ping from: " + pathCompressed);
-      yield* checkSize(pathCompressed);
-      return yield this.loadPingFile(pathCompressed, /* compressed*/ true);
+      await checkSize(pathCompressed);
+      return await this.loadPingFile(pathCompressed, /* compressed*/ true);
     } catch (ex) {
       if (!ex.becauseNoSuchFile) {
         throw ex;
       }
       // If that fails, look for the uncompressed version.
       this._log.trace("loadArchivedPing - compressed ping not found, loading: " + path);
-      yield* checkSize(path);
-      return yield this.loadPingFile(path, /* compressed*/ false);
+      await checkSize(path);
+      return await this.loadPingFile(path, /* compressed*/ false);
     }
-  }),
+  },
 
   /**
    * Saves session data to disk.
    */
   saveSessionData(sessionData) {
     return this._stateSaveSerializer.enqueueTask(() => this._saveSessionData(sessionData));
   },
 
-  _saveSessionData: Task.async(function* (sessionData) {
+  async _saveSessionData(sessionData) {
     let dataDir = OS.Path.join(OS.Constants.Path.profileDir, DATAREPORTING_DIR);
-    yield OS.File.makeDir(dataDir);
+    await OS.File.makeDir(dataDir);
 
     let filePath = OS.Path.join(gDataReportingDir, SESSION_STATE_FILE_NAME);
     try {
-      yield CommonUtils.writeJSON(sessionData, filePath);
+      await CommonUtils.writeJSON(sessionData, filePath);
     } catch (e) {
       this._log.error("_saveSessionData - Failed to write session data to " + filePath, e);
       Telemetry.getHistogramById("TELEMETRY_SESSIONDATA_FAILED_SAVE").add(1);
     }
-  }),
+  },
 
   /**
    * Loads session data from the session data file.
    * @return {Promise<Object>} A promise resolved with an object on success,
    *                           with null otherwise.
    */
   loadSessionData() {
     return this._stateSaveSerializer.enqueueTask(() => this._loadSessionData());
   },
 
-  _loadSessionData: Task.async(function* () {
+  async _loadSessionData() {
     const dataFile = OS.Path.join(OS.Constants.Path.profileDir, DATAREPORTING_DIR,
                                   SESSION_STATE_FILE_NAME);
     let content;
     try {
-      content = yield OS.File.read(dataFile, { encoding: "utf-8" });
+      content = await OS.File.read(dataFile, { encoding: "utf-8" });
     } catch (ex) {
       this._log.info("_loadSessionData - can not load session data file", ex);
       Telemetry.getHistogramById("TELEMETRY_SESSIONDATA_FAILED_LOAD").add(1);
       return null;
     }
 
     let data;
     try {
       data = JSON.parse(content);
     } catch (ex) {
       this._log.error("_loadSessionData - failed to parse session data", ex);
       Telemetry.getHistogramById("TELEMETRY_SESSIONDATA_FAILED_PARSE").add(1);
       return null;
     }
 
     return data;
-  }),
+  },
 
   /**
    * Remove an archived ping from disk.
    *
    * @param {string} id The pings id.
    * @param {number} timestampCreated The pings creation timestamp.
    * @param {string} type The pings type.
    * @return {promise<object>} Promise that is resolved when the pings is removed.
    */
-  _removeArchivedPing: Task.async(function*(id, timestampCreated, type) {
+  async _removeArchivedPing(id, timestampCreated, type) {
     this._log.trace("_removeArchivedPing - id: " + id + ", timestampCreated: " + timestampCreated + ", type: " + type);
     const path = getArchivedPingPath(id, new Date(timestampCreated), type);
     const pathCompressed = path + "lz4";
 
     this._log.trace("_removeArchivedPing - removing ping from: " + path);
-    yield OS.File.remove(path, {ignoreAbsent: true});
-    yield OS.File.remove(pathCompressed, {ignoreAbsent: true});
+    await OS.File.remove(path, {ignoreAbsent: true});
+    await OS.File.remove(pathCompressed, {ignoreAbsent: true});
     // Remove the ping from the cache.
     this._archivedPings.delete(id);
-  }),
+  },
 
   /**
    * Clean the pings archive by removing old pings.
    *
    * @return {Promise} Resolved when the cleanup task completes.
    */
   runCleanPingArchiveTask() {
     // If there's an archive cleaning task already running, return it.
@@ -817,23 +817,23 @@ var TelemetryStorageImpl = {
     this._cleanArchiveTask = this._cleanArchive().then(clear, clear);
     return this._cleanArchiveTask;
   },
 
   /**
    * Removes pings which are too old from the pings archive.
    * @return {Promise} Resolved when the ping age check is complete.
    */
-  _purgeOldPings: Task.async(function*() {
+  async _purgeOldPings() {
     this._log.trace("_purgeOldPings");
 
     const nowDate = Policy.now();
     const startTimeStamp = nowDate.getTime();
     let dirIterator = new OS.File.DirectoryIterator(gPingsArchivePath);
-    let subdirs = (yield dirIterator.nextBatch()).filter(e => e.isDir);
+    let subdirs = (await dirIterator.nextBatch()).filter(e => e.isDir);
     dirIterator.close();
 
     // Keep track of the newest removed month to update the cache, if needed.
     let newestRemovedMonthTimestamp = null;
     let evictedDirsCount = 0;
     let maxDirAgeInMonths = 0;
 
     // Walk through the monthly subdirs of the form <YYYY-MM>/
@@ -852,33 +852,33 @@ var TelemetryStorageImpl = {
       if (!archiveDate) {
         this._log.warn("_purgeOldPings - skipping invalid subdirectory date " + dir.path);
         continue;
       }
 
       // If this archive directory is older than 180 days, remove it.
       if ((startTimeStamp - archiveDate.getTime()) > MAX_ARCHIVED_PINGS_RETENTION_MS) {
         try {
-          yield OS.File.removeDir(dir.path);
+          await OS.File.removeDir(dir.path);
           evictedDirsCount++;
 
           // Update the newest removed month.
           newestRemovedMonthTimestamp = Math.max(archiveDate, newestRemovedMonthTimestamp);
         } catch (ex) {
           this._log.error("_purgeOldPings - Unable to remove " + dir.path, ex);
         }
       } else {
         // We're not removing this directory, so record the age for the oldest directory.
         const dirAgeInMonths = Utils.getElapsedTimeInMonths(archiveDate, nowDate);
         maxDirAgeInMonths = Math.max(dirAgeInMonths, maxDirAgeInMonths);
       }
     }
 
     // Trigger scanning of the archived pings.
-    yield this.loadArchivedPingList();
+    await this.loadArchivedPingList();
 
     // Refresh the cache: we could still skip this, but it's cheap enough to keep it
     // to avoid introducing task dependencies.
     if (newestRemovedMonthTimestamp) {
       // Scan the archive cache for pings older than the newest directory pruned above.
       for (let [id, info] of this._archivedPings) {
         const timestampCreated = new Date(info.timestampCreated);
         if (timestampCreated.getTime() > newestRemovedMonthTimestamp) {
@@ -893,23 +893,23 @@ var TelemetryStorageImpl = {
 
     // Save the time it takes to evict old directories and the eviction count.
     Telemetry.getHistogramById("TELEMETRY_ARCHIVE_EVICTED_OLD_DIRS")
              .add(evictedDirsCount);
     Telemetry.getHistogramById("TELEMETRY_ARCHIVE_EVICTING_DIRS_MS")
              .add(Math.ceil(endTimeStamp - startTimeStamp));
     Telemetry.getHistogramById("TELEMETRY_ARCHIVE_OLDEST_DIRECTORY_AGE")
              .add(maxDirAgeInMonths);
-  }),
+  },
 
   /**
    * Enforce a disk quota for the pings archive.
    * @return {Promise} Resolved when the quota check is complete.
    */
-  _enforceArchiveQuota: Task.async(function*() {
+  async _enforceArchiveQuota() {
     this._log.trace("_enforceArchiveQuota");
     let startTimeStamp = Policy.now().getTime();
 
     // Build an ordered list, from newer to older, of archived pings.
     let pingList = Array.from(this._archivedPings, p => ({
       id: p[0],
       timestampCreated: p[1].timestampCreated,
       type: p[1].type,
@@ -930,28 +930,28 @@ var TelemetryStorageImpl = {
         this._log.trace("_enforceArchiveQuota - Terminating the clean up task due to shutdown");
         return;
       }
 
       let ping = pingList[i];
 
       // Get the size for this ping.
       const fileSize =
-        yield getArchivedPingSize(ping.id, new Date(ping.timestampCreated), ping.type);
+        await getArchivedPingSize(ping.id, new Date(ping.timestampCreated), ping.type);
       if (!fileSize) {
         this._log.warn("_enforceArchiveQuota - Unable to find the size of ping " + ping.id);
         continue;
       }
 
       // Enforce a maximum file size limit on archived pings.
       if (fileSize > PING_FILE_MAXIMUM_SIZE_BYTES) {
         this._log.error("_enforceArchiveQuota - removing file exceeding size limit, size: " + fileSize);
         // We just remove the ping from the disk, we don't bother removing it from pingList
         // since it won't contribute to the quota.
-        yield this._removeArchivedPing(ping.id, ping.timestampCreated, ping.type)
+        await this._removeArchivedPing(ping.id, ping.timestampCreated, ping.type)
                   .catch(e => this._log.error("_enforceArchiveQuota - failed to remove archived ping" + ping.id));
         Telemetry.getHistogramById("TELEMETRY_DISCARDED_ARCHIVED_PINGS_SIZE_MB")
                  .add(Math.floor(fileSize / 1024 / 1024));
         Telemetry.getHistogramById("TELEMETRY_PING_SIZE_EXCEEDED_ARCHIVED").add();
         continue;
       }
 
       archiveSizeInBytes += fileSize;
@@ -992,68 +992,68 @@ var TelemetryStorageImpl = {
     for (let ping of pingsToPurge) {
       if (this._shutdown) {
         this._log.trace("_enforceArchiveQuota - Terminating the clean up task due to shutdown");
         return;
       }
 
       // This list is guaranteed to be in order, so remove the pings at its
       // beginning (oldest).
-      yield this._removeArchivedPing(ping.id, ping.timestampCreated, ping.type);
+      await this._removeArchivedPing(ping.id, ping.timestampCreated, ping.type);
     }
 
     const endTimeStamp = Policy.now().getTime();
     submitProbes(ARCHIVE_SIZE_PROBE_SPECIAL_VALUE, pingsToPurge.length,
                  Math.ceil(endTimeStamp - startTimeStamp));
-  }),
+  },
 
-  _cleanArchive: Task.async(function*() {
+  async _cleanArchive() {
     this._log.trace("cleanArchiveTask");
 
-    if (!(yield OS.File.exists(gPingsArchivePath))) {
+    if (!(await OS.File.exists(gPingsArchivePath))) {
       return;
     }
 
     // Remove pings older than 180 days.
     try {
-      yield this._purgeOldPings();
+      await this._purgeOldPings();
     } catch (ex) {
       this._log.error("_cleanArchive - There was an error removing old directories", ex);
     }
 
     // Make sure we respect the archive disk quota.
-    yield this._enforceArchiveQuota();
-  }),
+    await this._enforceArchiveQuota();
+  },
 
   /**
    * Run the task to enforce the pending pings quota.
    *
    * @return {Promise} Resolved when the cleanup task completes.
    */
-  runEnforcePendingPingsQuotaTask: Task.async(function*() {
+  async runEnforcePendingPingsQuotaTask() {
     // If there's a cleaning task already running, return it.
     if (this._enforcePendingPingsQuotaTask) {
       return this._enforcePendingPingsQuotaTask;
     }
 
     // Since there's no quota enforcing task running, start it.
     try {
       this._enforcePendingPingsQuotaTask = this._enforcePendingPingsQuota();
-      yield this._enforcePendingPingsQuotaTask;
+      await this._enforcePendingPingsQuotaTask;
     } finally {
       this._enforcePendingPingsQuotaTask = null;
     }
     return undefined;
-  }),
+  },
 
   /**
    * Enforce a disk quota for the pending pings.
    * @return {Promise} Resolved when the quota check is complete.
    */
-  _enforcePendingPingsQuota: Task.async(function*() {
+  async _enforcePendingPingsQuota() {
     this._log.trace("_enforcePendingPingsQuota");
     let startTimeStamp = Policy.now().getTime();
 
     // Build an ordered list, from newer to older, of pending pings.
     let pingList = Array.from(this._pendingPings, p => ({
       id: p[0],
       lastModificationDate: p[1].lastModificationDate,
     }));
@@ -1072,17 +1072,17 @@ var TelemetryStorageImpl = {
       if (this._shutdown) {
         this._log.trace("_enforcePendingPingsQuota - Terminating the clean up task due to shutdown");
         return;
       }
 
       let ping = pingList[i];
 
       // Get the size for this ping.
-      const fileSize = yield getPendingPingSize(ping.id);
+      const fileSize = await getPendingPingSize(ping.id);
       if (!fileSize) {
         this._log.warn("_enforcePendingPingsQuota - Unable to find the size of ping " + ping.id);
         continue;
       }
 
       pendingPingsSizeInBytes += fileSize;
       if (pendingPingsSizeInBytes < SAFE_QUOTA) {
         // We save the index of the last ping which is ok to keep in order to speed up ping
@@ -1120,26 +1120,26 @@ var TelemetryStorageImpl = {
     for (let ping of pingsToPurge) {
       if (this._shutdown) {
         this._log.trace("_enforcePendingPingsQuota - Terminating the clean up task due to shutdown");
         return;
       }
 
       // This list is guaranteed to be in order, so remove the pings at its
       // beginning (oldest).
-      yield this.removePendingPing(ping.id);
+      await this.removePendingPing(ping.id);
     }
 
     const endTimeStamp = Policy.now().getTime();
     // We don't know the size of the pending pings directory if we are above the quota,
     // since we stop scanning once we reach the quota. We use a special value to show
     // this condition.
     recordHistograms(PENDING_PINGS_SIZE_PROBE_SPECIAL_VALUE, pingsToPurge.length,
                  Math.ceil(endTimeStamp - startTimeStamp));
-  }),
+  },
 
   /**
    * Reset the storage state in tests.
    */
   reset() {
     this._shutdown = false;
     this._scannedArchiveDirectory = false;
     this._archivedPings = new Map();
@@ -1149,65 +1149,65 @@ var TelemetryStorageImpl = {
 
   /**
    * Get a list of info on the archived pings.
    * This will scan the archive directory and grab basic data about the existing
    * pings out of their filename.
    *
    * @return {promise<sequence<object>>}
    */
-  loadArchivedPingList: Task.async(function*() {
+  async loadArchivedPingList() {
     // If there's an archive loading task already running, return it.
     if (this._scanArchiveTask) {
       return this._scanArchiveTask;
     }
 
-    yield waitForAll(this._activelyArchiving);
+    await waitForAll(this._activelyArchiving);
 
     if (this._scannedArchiveDirectory) {
       this._log.trace("loadArchivedPingList - Archive already scanned, hitting cache.");
       return this._archivedPings;
     }
 
     // Since there's no archive loading task running, start it.
     let result;
     try {
       this._scanArchiveTask = this._scanArchive();
-      result = yield this._scanArchiveTask;
+      result = await this._scanArchiveTask;
     } finally {
       this._scanArchiveTask = null;
     }
     return result;
-  }),
+  },
 
-  _scanArchive: Task.async(function*() {
+  async _scanArchive() {
     this._log.trace("_scanArchive");
 
     let submitProbes = (pingCount, dirCount) => {
       Telemetry.getHistogramById("TELEMETRY_ARCHIVE_SCAN_PING_COUNT")
                .add(pingCount);
       Telemetry.getHistogramById("TELEMETRY_ARCHIVE_DIRECTORIES_COUNT")
                .add(dirCount);
     };
 
-    if (!(yield OS.File.exists(gPingsArchivePath))) {
+    if (!(await OS.File.exists(gPingsArchivePath))) {
       submitProbes(0, 0);
       return new Map();
     }
 
     let dirIterator = new OS.File.DirectoryIterator(gPingsArchivePath);
     let subdirs =
-      (yield dirIterator.nextBatch()).filter(e => e.isDir).filter(e => isValidArchiveDir(e.name));
+        (await dirIterator.nextBatch()).filter(e => e.isDir).filter(e => isValidArchiveDir(e.name));
     dirIterator.close();
 
     // Walk through the monthly subdirs of the form <YYYY-MM>/
     for (let dir of subdirs) {
       this._log.trace("_scanArchive - checking in subdir: " + dir.path);
       let pingIterator = new OS.File.DirectoryIterator(dir.path);
-      let pings = (yield pingIterator.nextBatch()).filter(e => !e.isDir);
+      let pings = (await pingIterator.nextBatch()).filter(e => !e.isDir);
       pingIterator.close();
 
       // Now process any ping files of the form "<timestamp>.<uuid>.<type>.[json|jsonlz4]".
       for (let p of pings) {
         // data may be null if the filename doesn't match the above format.
         let data = this._getArchivedPingDataFromFileName(p.name);
         if (!data) {
           continue;
@@ -1217,76 +1217,76 @@ var TelemetryStorageImpl = {
         if (this._archivedPings.has(data.id)) {
           const overwrite = data.timestamp > this._archivedPings.get(data.id).timestampCreated;
           this._log.warn("_scanArchive - have seen this id before: " + data.id +
                          ", overwrite: " + overwrite);
           if (!overwrite) {
             continue;
           }
 
-          yield this._removeArchivedPing(data.id, data.timestampCreated, data.type)
+          await this._removeArchivedPing(data.id, data.timestampCreated, data.type)
                     .catch((e) => this._log.warn("_scanArchive - failed to remove ping", e));
         }
 
         this._archivedPings.set(data.id, {
           timestampCreated: data.timestamp,
           type: internString(data.type),
         });
       }
     }
 
     // Mark the archive as scanned, so we no longer hit the disk.
     this._scannedArchiveDirectory = true;
     // Update the ping and directories count histograms.
     submitProbes(this._archivedPings.size, subdirs.length);
     return this._archivedPings;
-  }),
+  },
 
   /**
    * Save a single ping to a file.
    *
    * @param {object} ping The content of the ping to save.
    * @param {string} file The destination file.
    * @param {bool} overwrite If |true|, the file will be overwritten if it exists,
    * if |false| the file will not be overwritten and no error will be reported if
    * the file exists.
    * @param {bool} [compress=false] If |true|, the file will use lz4 compression. Otherwise no
    * compression will be used.
    * @returns {promise}
    */
-  savePingToFile: Task.async(function*(ping, filePath, overwrite, compress = false) {
+  async savePingToFile(ping, filePath, overwrite, compress = false) {
     try {
       this._log.trace("savePingToFile - path: " + filePath);
       let pingString = JSON.stringify(ping);
       let options = { tmpPath: filePath + ".tmp", noOverwrite: !overwrite };
       if (compress) {
         options.compression = "lz4";
       }
-      yield OS.File.writeAtomic(filePath, pingString, options);
+      await OS.File.writeAtomic(filePath, pingString, options);
     } catch (e) {
       if (!e.becauseExists) {
         throw e;
       }
     }
-  }),
+  },
 
   /**
    * Save a ping to its file.
    *
    * @param {object} ping The content of the ping to save.
    * @param {bool} overwrite If |true|, the file will be overwritten
    * if it exists.
    * @returns {promise}
    */
-  savePing: Task.async(function*(ping, overwrite) {
-    yield getPingDirectory();
+  async savePing(ping, overwrite) {
+    await getPingDirectory();
     let file = pingFilePath(ping);
-    yield this.savePingToFile(ping, file, overwrite);
+    await this.savePingToFile(ping, file, overwrite);
     return file;
-  }),
+  },
 
   /**
    * Add a ping to the saved pings directory so that it gets saved
    * and sent along with other pings.
    * Note: that the original ping file will not be modified.
    *
    * @param {Object} ping The ping object.
    * @return {Promise} A promise resolved when the ping is saved to the pings directory.
@@ -1312,63 +1312,63 @@ var TelemetryStorageImpl = {
         lastModificationDate: Policy.now().getTime(),
       });
       this._log.trace("savePendingPing - saved ping with id " + ping.id);
     });
     this._trackPendingPingSaveTask(p);
     return p;
   },
 
-  loadPendingPing: Task.async(function*(id) {
+  async loadPendingPing(id) {
     this._log.trace("loadPendingPing - id: " + id);
     let info = this._pendingPings.get(id);
     if (!info) {
       this._log.trace("loadPendingPing - unknown id " + id);
       throw new Error("TelemetryStorage.loadPendingPing - no ping with id " + id);
     }
 
     // Try to get the dimension of the ping. If that fails, update the histograms.
     let fileSize = 0;
     try {
-      fileSize = (yield OS.File.stat(info.path)).size;
+      fileSize = (await OS.File.stat(info.path)).size;
     } catch (e) {
       if (!(e instanceof OS.File.Error) || !e.becauseNoSuchFile) {
         throw e;
       }
       // Fall through and let |loadPingFile| report the error.
     }
 
     // Purge pings which are too big.
     if (fileSize > PING_FILE_MAXIMUM_SIZE_BYTES) {
-      yield this.removePendingPing(id);
+      await this.removePendingPing(id);
       Telemetry.getHistogramById("TELEMETRY_DISCARDED_PENDING_PINGS_SIZE_MB")
                .add(Math.floor(fileSize / 1024 / 1024));
       Telemetry.getHistogramById("TELEMETRY_PING_SIZE_EXCEEDED_PENDING").add();
       throw new Error("loadPendingPing - exceeded the maximum ping size: " + fileSize);
     }
 
     // Try to load the ping file. Update the related histograms on failure.
     let ping;
     try {
-      ping = yield this.loadPingFile(info.path, false);
+      ping = await this.loadPingFile(info.path, false);
     } catch (e) {
       // If we failed to load the ping, check what happened and update the histogram.
       if (e instanceof PingReadError) {
         Telemetry.getHistogramById("TELEMETRY_PENDING_LOAD_FAILURE_READ").add();
       } else if (e instanceof PingParseError) {
         Telemetry.getHistogramById("TELEMETRY_PENDING_LOAD_FAILURE_PARSE").add();
       }
       // Remove the ping from the cache, so we don't try to load it again.
       this._pendingPings.delete(id);
       // Then propagate the rejection.
       throw e;
     }
 
     return ping;
-  }),
+  },
 
   removePendingPing(id) {
     let info = this._pendingPings.get(id);
     if (!info) {
       this._log.trace("removePendingPing - unknown id " + id);
       return Promise.resolve();
     }
 
@@ -1402,62 +1402,62 @@ var TelemetryStorageImpl = {
     return waitForAll(this._activePendingPingSaves);
   },
 
   /**
    * Run the task to remove all the pending pings (except the deletion ping).
    *
    * @return {Promise} Resolved when the pings are removed.
    */
-  runRemovePendingPingsTask: Task.async(function*() {
+  async runRemovePendingPingsTask() {
     // If we already have a pending pings removal task active, return that.
     if (this._removePendingPingsTask) {
       return this._removePendingPingsTask;
     }
 
     // Start the task to remove all pending pings. Also make sure to clear the task once done.
     try {
       this._removePendingPingsTask = this.removePendingPings();
-      yield this._removePendingPingsTask;
+      await this._removePendingPingsTask;
     } finally {
       this._removePendingPingsTask = null;
     }
     return undefined;
-  }),
+  },
 
-  removePendingPings: Task.async(function*() {
+  async removePendingPings() {
     this._log.trace("removePendingPings - removing all pending pings");
 
     // Wait on pending pings still being saved, so so we don't miss removing them.
-    yield this.promisePendingPingSaves();
+    await this.promisePendingPingSaves();
 
     // Individually remove existing pings, so we don't interfere with operations expecting
     // the pending pings directory to exist.
     const directory = TelemetryStorage.pingDirectoryPath;
     let iter = new OS.File.DirectoryIterator(directory);
 
     try {
-      if (!(yield iter.exists())) {
+      if (!(await iter.exists())) {
         this._log.trace("removePendingPings - the pending pings directory doesn't exist");
         return;
       }
 
-      let files = (yield iter.nextBatch()).filter(e => !e.isDir);
+      let files = (await iter.nextBatch()).filter(e => !e.isDir);
       for (let file of files) {
         try {
-          yield OS.File.remove(file.path);
+          await OS.File.remove(file.path);
         } catch (ex) {
           this._log.error("removePendingPings - failed to remove file " + file.path, ex);
           continue;
         }
       }
     } finally {
-      yield iter.close();
+      await iter.close();
     }
-  }),
+  },
 
   loadPendingPingList() {
     // If we already have a pending scanning task active, return that.
     if (this._scanPendingPingsTask) {
       return this._scanPendingPingsTask;
     }
 
     if (this._scannedPendingDirectory) {
@@ -1476,48 +1476,48 @@ var TelemetryStorageImpl = {
     });
     return this._scanPendingPingsTask;
   },
 
   getPendingPingList() {
     return this._buildPingList();
   },
 
-  _scanPendingPings: Task.async(function*() {
+  async _scanPendingPings() {
     this._log.trace("_scanPendingPings");
 
     let directory = TelemetryStorage.pingDirectoryPath;
     let iter = new OS.File.DirectoryIterator(directory);
-    let exists = yield iter.exists();
+    let exists = await iter.exists();
 
     try {
       if (!exists) {
         return [];
       }
 
-      let files = (yield iter.nextBatch()).filter(e => !e.isDir);
+      let files = (await iter.nextBatch()).filter(e => !e.isDir);
 
       for (let file of files) {
         if (this._shutdown) {
           return [];
         }
 
         let info;
         try {
-          info = yield OS.File.stat(file.path);
+          info = await OS.File.stat(file.path);
         } catch (ex) {
           this._log.error("_scanPendingPings - failed to stat file " + file.path, ex);
           continue;
         }
 
         // Enforce a maximum file size limit on pending pings.
         if (info.size > PING_FILE_MAXIMUM_SIZE_BYTES) {
           this._log.error("_scanPendingPings - removing file exceeding size limit " + file.path);
           try {
-            yield OS.File.remove(file.path);
+            await OS.File.remove(file.path);
           } catch (ex) {
             this._log.error("_scanPendingPings - failed to remove file " + file.path, ex);
           } finally {
             Telemetry.getHistogramById("TELEMETRY_DISCARDED_PENDING_PINGS_SIZE_MB")
                      .add(Math.floor(info.size / 1024 / 1024));
             Telemetry.getHistogramById("TELEMETRY_PING_SIZE_EXCEEDED_PENDING").add();
           }
           continue;
@@ -1530,33 +1530,33 @@ var TelemetryStorageImpl = {
         }
 
         this._pendingPings.set(id, {
           path: file.path,
           lastModificationDate: info.lastModificationDate.getTime(),
         });
       }
     } finally {
-      yield iter.close();
+      await iter.close();
     }
 
     // Explicitly load the deletion ping from its known path, if it's there.
-    if (yield OS.File.exists(gDeletionPingFilePath)) {
+    if (await OS.File.exists(gDeletionPingFilePath)) {
       this._log.trace("_scanPendingPings - Adding pending deletion ping.");
       // We can't get the ping id or the last modification date without hitting the disk.
       // Since deletion has a special handling, we don't really need those.
       this._pendingPings.set(Utils.generateUUID(), {
         path: gDeletionPingFilePath,
         lastModificationDate: Date.now(),
       });
     }
 
     this._scannedPendingDirectory = true;
     return this._buildPingList();
-  }),
+  },
 
   _buildPingList() {
     const list = Array.from(this._pendingPings, p => ({
       id: p[0],
       lastModificationDate: p[1].lastModificationDate,
     }));
 
     list.sort((a, b) => b.lastModificationDate - a.lastModificationDate);
@@ -1571,45 +1571,45 @@ var TelemetryStorageImpl = {
    * Loads a ping file.
    * @param {String} aFilePath The path of the ping file.
    * @param {Boolean} [aCompressed=false] If |true|, expects the file to be compressed using lz4.
    * @return {Promise<Object>} A promise resolved with the ping content or rejected if the
    *                           ping contains invalid data.
    * @throws {PingReadError} There was an error while reading the ping file from the disk.
    * @throws {PingParseError} There was an error while parsing the JSON content of the ping file.
    */
-  loadPingFile: Task.async(function* (aFilePath, aCompressed = false) {
+  async loadPingFile(aFilePath, aCompressed = false) {
     let options = {};
     if (aCompressed) {
       options.compression = "lz4";
     }
 
     let array;
     try {
-      array = yield OS.File.read(aFilePath, options);
+      array = await OS.File.read(aFilePath, options);
     } catch (e) {
       this._log.trace("loadPingfile - unreadable ping " + aFilePath, e);
       throw new PingReadError(e.message, e.becauseNoSuchFile);
     }
 
     let decoder = new TextDecoder();
     let string = decoder.decode(array);
     let ping;
     try {
       ping = JSON.parse(string);
     } catch (e) {
       this._log.trace("loadPingfile - unparseable ping " + aFilePath, e);
-      yield OS.File.remove(aFilePath).catch((ex) => {
+      await OS.File.remove(aFilePath).catch((ex) => {
         this._log.error("loadPingFile - failed removing unparseable ping file", ex);
       });
       throw new PingParseError(e.message);
     }
 
     return ping;
-  }),
+  },
 
   /**
    * Archived pings are saved with file names of the form:
    * "<timestamp>.<uuid>.<type>.[json|jsonlz4]"
    * This helper extracts that data from a given filename.
    *
    * @param fileName {String} The filename.
    * @return {Object} Null if the filename didn't match the expected form.
@@ -1654,86 +1654,86 @@ var TelemetryStorageImpl = {
 
     return {
       timestamp,
       id: uuid,
       type,
     };
   },
 
-  saveAbortedSessionPing: Task.async(function*(ping) {
+  async saveAbortedSessionPing(ping) {
     this._log.trace("saveAbortedSessionPing - ping path: " + gAbortedSessionFilePath);
-    yield OS.File.makeDir(gDataReportingDir, { ignoreExisting: true });
+    await OS.File.makeDir(gDataReportingDir, { ignoreExisting: true });
 
     return this._abortedSessionSerializer.enqueueTask(() =>
       this.savePingToFile(ping, gAbortedSessionFilePath, true));
-  }),
+  },
 
-  loadAbortedSessionPing: Task.async(function*() {
+  async loadAbortedSessionPing() {
     let ping = null;
     try {
-      ping = yield this.loadPingFile(gAbortedSessionFilePath);
+      ping = await this.loadPingFile(gAbortedSessionFilePath);
     } catch (ex) {
       if (ex.becauseNoSuchFile) {
         this._log.trace("loadAbortedSessionPing - no such file");
       } else {
         this._log.error("loadAbortedSessionPing - error loading ping", ex)
       }
     }
     return ping;
-  }),
+  },
 
   removeAbortedSessionPing() {
-    return this._abortedSessionSerializer.enqueueTask(Task.async(function*() {
+    return this._abortedSessionSerializer.enqueueTask(async function() {
       try {
-        yield OS.File.remove(gAbortedSessionFilePath, { ignoreAbsent: false });
+        await OS.File.remove(gAbortedSessionFilePath, { ignoreAbsent: false });
         this._log.trace("removeAbortedSessionPing - success");
       } catch (ex) {
         if (ex.becauseNoSuchFile) {
           this._log.trace("removeAbortedSessionPing - no such file");
         } else {
           this._log.error("removeAbortedSessionPing - error removing ping", ex)
         }
       }
-    }.bind(this)));
+    }.bind(this));
   },
 
   /**
    * Save the deletion ping.
    * @param ping The deletion ping.
    * @return {Promise} Resolved when the ping is saved.
    */
-  saveDeletionPing: Task.async(function*(ping) {
+  async saveDeletionPing(ping) {
     this._log.trace("saveDeletionPing - ping path: " + gDeletionPingFilePath);
-    yield OS.File.makeDir(gDataReportingDir, { ignoreExisting: true });
+    await OS.File.makeDir(gDataReportingDir, { ignoreExisting: true });
 
     let p = this._deletionPingSerializer.enqueueTask(() =>
       this.savePingToFile(ping, gDeletionPingFilePath, true));
     this._trackPendingPingSaveTask(p);
     return p;
-  }),
+  },
 
   /**
    * Remove the deletion ping.
    * @return {Promise} Resolved when the ping is deleted from the disk.
    */
-  removeDeletionPing: Task.async(function*() {
-    return this._deletionPingSerializer.enqueueTask(Task.async(function*() {
+  async removeDeletionPing() {
+    return this._deletionPingSerializer.enqueueTask(async function() {
       try {
-        yield OS.File.remove(gDeletionPingFilePath, { ignoreAbsent: false });
+        await OS.File.remove(gDeletionPingFilePath, { ignoreAbsent: false });
         this._log.trace("removeDeletionPing - success");
       } catch (ex) {
         if (ex.becauseNoSuchFile) {
           this._log.trace("removeDeletionPing - no such file");
         } else {
           this._log.error("removeDeletionPing - error removing ping", ex)
         }
       }
-    }.bind(this)));
-  }),
+    }.bind(this));
+  },
 
   isDeletionPing(aPingId) {
     let pingInfo = this._pendingPings.get(aPingId);
     if (!pingInfo) {
       return false;
     }
 
     if (pingInfo.path != gDeletionPingFilePath) {
@@ -1743,17 +1743,17 @@ var TelemetryStorageImpl = {
     return true;
   },
 
   /**
    * Remove FHR database files. This is temporary and will be dropped in
    * the future.
    * @return {Promise} Resolved when the database files are deleted.
    */
-  removeFHRDatabase: Task.async(function*() {
+  async removeFHRDatabase() {
     this._log.trace("removeFHRDatabase");
 
     // Let's try to remove the FHR DB with the default filename first.
     const FHR_DB_DEFAULT_FILENAME = "healthreport.sqlite";
 
     // Even if it's uncommon, there may be 2 additional files: - a "write ahead log"
     // (-wal) file and a "shared memory file" (-shm). We need to remove them as well.
     let FILES_TO_REMOVE = [
@@ -1769,40 +1769,40 @@ var TelemetryStorageImpl = {
     if (FHR_DB_CUSTOM_FILENAME) {
       FILES_TO_REMOVE.push(
         OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME),
         OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME + "-wal"),
         OS.Path.join(OS.Constants.Path.profileDir, FHR_DB_CUSTOM_FILENAME + "-shm"));
     }
 
     for (let f of FILES_TO_REMOVE) {
-      yield OS.File.remove(f, {ignoreAbsent: true})
+      await OS.File.remove(f, {ignoreAbsent: true})
                    .catch(e => this._log.error("removeFHRDatabase - failed to remove " + f, e));
     }
-  }),
+  },
 };
 
 // Utility functions
 
 function pingFilePath(ping) {
   // Support legacy ping formats, who don't have an "id" field, but a "slug" field.
   let pingIdentifier = (ping.slug) ? ping.slug : ping.id;
   return OS.Path.join(TelemetryStorage.pingDirectoryPath, pingIdentifier);
 }
 
 function getPingDirectory() {
-  return Task.spawn(function*() {
+  return (async function() {
     let directory = TelemetryStorage.pingDirectoryPath;
 
-    if (!(yield OS.File.exists(directory))) {
-      yield OS.File.makeDir(directory, { unixMode: OS.Constants.S_IRWXU });
+    if (!(await OS.File.exists(directory))) {
+      await OS.File.makeDir(directory, { unixMode: OS.Constants.S_IRWXU });
     }
 
     return directory;
-  });
+  })();
 }
 
 /**
  * Build the path to the archived ping.
  * @param {String} aPingId The ping id.
  * @param {Object} aDate The ping creation date.
  * @param {String} aType The ping type.
  * @return {String} The full path to the archived ping.
@@ -1817,43 +1817,43 @@ function getArchivedPingPath(aPingId, aD
   let fileName = [aDate.getTime(), aPingId, aType, "json"].join(".");
   return OS.Path.join(archivedPingDir, fileName);
 }
 
 /**
  * Get the size of the ping file on the disk.
  * @return {Integer} The file size, in bytes, of the ping file or 0 on errors.
  */
-var getArchivedPingSize = Task.async(function*(aPingId, aDate, aType) {
+var getArchivedPingSize = async function(aPingId, aDate, aType) {
   const path = getArchivedPingPath(aPingId, aDate, aType);
   let filePaths = [ path + "lz4", path ];
 
   for (let path of filePaths) {
     try {
-      return (yield OS.File.stat(path)).size;
+      return (await OS.File.stat(path)).size;
     } catch (e) {}
   }
 
   // That's odd, this ping doesn't seem to exist.
   return 0;
-});
+};
 
 /**
  * Get the size of the pending ping file on the disk.
  * @return {Integer} The file size, in bytes, of the ping file or 0 on errors.
  */
-var getPendingPingSize = Task.async(function*(aPingId) {
+var getPendingPingSize = async function(aPingId) {
   const path = OS.Path.join(TelemetryStorage.pingDirectoryPath, aPingId)
   try {
-    return (yield OS.File.stat(path)).size;
+    return (await OS.File.stat(path)).size;
   } catch (e) {}
 
   // That's odd, this ping doesn't seem to exist.
   return 0;
-});
+};
 
 /**
  * Check if a directory name is in the "YYYY-MM" format.
  * @param {String} aDirName The name of the pings archive directory.
  * @return {Boolean} True if the directory name is in the right format, false otherwise.
  */
 function isValidArchiveDir(aDirName) {
   const dirRegEx = /^[0-9]{4}-[0-9]{2}$/;