plugins/network/s3_transfer.js

const fs = require('fs');
const { OperationResult } = require('../../core/operation_result');

/**
 * S3Transfer keeps track of information about an upload or
 * download operation being performed by the S3Client plugin.
 * It also contains the {@link OperationResult} record that the
 * {@link S3Client} will return when it emits its finish event.
 *
 * There is some overlap between info contained in an S3Transfer
 * and the info in an {@link OperationResult}. The S3Transfer
 * record is for the {@link S3Client|S3Client's} internal use,
 * and includes information that is not useful to any other plugin.
 *
 * The {@link OperationResult} is an object intended to be returned
 * or emitted by many plugins to describe the outcode of their work
 * in a uniform manner.
 *
 */
class S3Transfer {
    /**
     * Creates a new S3Transfer object.
     *
     * @param {string} operation - The name of the operation that the
     * S3Client will perform. This should be 'upload' or 'download'.
     *
     * @param {string} provider - The name of the provilder (Plugin)
     * performing the operation.
     */
    constructor(operation, provider) {
        /**
         * The name of the S3 operation. This should be either
         * 'upload' or 'download'.
         *
         * @type {string}
         */
        this.operation = operation;
        /**
         * The name or IP address of the S3 host.
         *
         * @type {string}
         */
        this.host = '';
        /**
         * The port number of the S3 host that our client should
         * connect to. You can usually leave this blank.
         *
         * @type {number}
         */
        this.port = null;
        /**
         * The name of the bucket on the S3 server to which we should
         * upload or from which we should download.
         *
         * @type {string}
         */
        this.bucket = '';
        /**
         * The name of the key (a.k.a the object name) on the S3 server
         * that we want to put or get.
         *
         * @type {string}
         */
        this.key = '';
        /**
         * The path to the file on the locally mounted filesystem that
         * we want to upload to S3 in an upload operation. For downloads,
         * this is the path to which we'll save the S3 object we retrieve.
         *
         * @type {string}
         */
        this.localPath = '';
        /**
         * An fs.stats object describing the size, mtime, uid, etc. of the
         * file at localPath. For uploads, this will be set before the
         * upload begins. For downloads, it will be set after the download
         * completes.
         *
         * @type {fs.stats}
         */
        this.localStat = null;
        /**
         * An object describing the size and etag of an object uploaded to
         * S3. For uploads, this will be set after the upload completes.
         * For downloads, it will remain null.
         *
         * @type {fs.stats}
         */
        this.remoteStat = null;
        /**
         * The etag of a file uploaded to S3. This will be set after the
         * upload completes. For downloads, it will remain null.
         *
         * @type {string}
         */
        this.etag = '';
        /**
         * The last error to occur during an operation by the S3 client.
         * For a full list of errors, check the result.errors list.
         *
         * @type {string}
         */
        this.error = null;
        /**
         * The number of bytes transferred to or from the remote host.
         *
         * @type {number}
         */
        this.bytesTransferred = 0;
        /**
         * An object describing the outcome of an upload or download
         * operation, including any errors that may have occurred.
         *
         * @type {OperationResult}
         */
        this.result = new OperationResult(operation, provider);
    }

    /**
     * This returns the URL of the object on the S3 server that we are
     * trying to upload or download.
     *
     * @returns {string}
     */
    getRemoteUrl() {
        let url = 'https://' + this.host.replace('/','');
        if (this.port) {
            url += `:${this.port}`;
        }
        url += `/${this.bucket}/${this.key}`;
        return url;
    }

    percentComplete() {
        let size = this.operation == 'upload' ? this.localStat.size : this.remoteStat.size;
        let percentComplete = 0;
        if (size > 0) {
            percentComplete = (this.bytesTransferred / size) * 100;
        }
        return percentComplete;
    }

}

module.exports.S3Transfer = S3Transfer;