В GCF нет такого объекта, когда рассматриваемый объект был только что создан

Я настраиваю функцию Google Cloud Functions (GCF), которая запускается достаточно часто, чтобы одновременно работало несколько экземпляров.

Я получаю ошибки из readStream, исходный файл потока не существует, но на данный момент в моей программе я фактически только что создал его.

Я убедился, что файл существует до начала потока с помощью console.log () -ing файла JSON, поэтому файл действительно действительно существует. Я также убедился, что файл, к которому я пытаюсь получить доступ, закончил запись предыдущим потоком с ожиданием, но без кубиков.

РЕДАКТИРОВАТЬ: теперь код содержит весь скрипт. Раздел, который, кажется, вызывает ошибку, - это функция columnDelete ().

var parse = require('fast-csv');
var Storage = require('@google-cloud/storage');
var Transform = require('readable-stream').Transform;

var storage = new Storage();
var bucket = storage.bucket('<BUCKET>');
const DMSs = ['PBS','CDK','One_Eighty','InfoBahn'];


class DeleteColumns extends Transform{
    constructor(){
        super({objectMode:true})
    }
    _transform(row, enc, done){
        //create an array 2 elements shorter than received
        let newRow = new Array(row.length - 2);

        //write all data but the first two columns
        for(let i = 0; i < newRow.length; i++){
            newRow[i] = row[i+2];
        }

        this.push(newRow.toString() + '\n');
        done();
    }
}


function rename(file, originalFile, DMS){
    return new Promise((resolve, reject) => {
        var dealer;
        var date;
        var header = true;
        var parser = parse({delimiter : ",", quote:'\\'});

        //for each row of data
        var stream = originalFile.createReadStream();
        stream.pipe(parser)
        .on('data', (row)=>{


            //if this is the first line do nothing
            if(header){
                header = false;
            }
            //otherwise record the contents of the first two columns and then destroy the stream
            else {
                dealer = row[0].toString().replace('"', '').replace('"', '');
                date = row[1].toString().replace('"', '').replace('"', '');

                stream.end();
            }
        })
        .on('finish', function(){
            var newName = dealer + ' ' + date + '_' + DMS + 'temp.csv';
            //if this was not triggered by the renaming of a file
            if(!file.name.includes(dealer)&&!file.name.includes(':')){
                console.log('Renamed ' + file.name);
                originalFile.copy(newName);
                originalFile.copy(newName.replace('temp',''));
            }else{
                newName = 'Not Renamed';
                console.log('Oops, triggered by the rename');
            }
            resolve(newName);

        });
    });

}
function columnDelete(fileName){
    return new Promise((resolve, reject) =>{
        console.log('Deleting Columns...');
        console.log(bucket.file(fileName));
        var parser = parse({delimiter : ",", quote:'\\'});
        var del = new DeleteColumns();
        var temp = bucket.file(fileName);
        var final = bucket.file(fileName.replace('temp', ''));

        //for each row of data
        temp.createReadStream()
        //parse the csv
        .pipe(parser)
        //delete first two columns
        .pipe(del)
        //write to new file
        .pipe(final.createWriteStream()
            .on('finish', function(){
                console.log('Columns Deleted');
                temp.delete();
                resolve();
            })
        );
    });

}

exports.triggerRename = async(data, context) => {
    var DMS = 'Triple';
    var file = data;
    //if not a temporary file
    if(!file.name.includes('temp')){

        //create a new File object from the name of the data passed
        const originalFile = bucket.file(file.name);

        //identify which database this data is from
        DMSs.forEach(function(database){
            if(file.name.includes(database)){
                DMS = database;
            }
        });
        //rename the file
        var tempName = await rename(file, originalFile, DMS);
        //if it was renamed, delete the extra columns
        if (!tempName.includes('Not Renamed')){
            await columnDelete(tempName);
        }

    } else if(file.name.includes('undefined')){
        console.log(file.name + ' is invalid. Deleted.');
        bucket.file(file.name).delete();
    }
     else {
        console.log( file.name + ' is a temporary file. Did not rename.');
    }
};

Я ожидаю, что результат будет следующим:

Deleting Columns...
Columns Deleted

Красиво и просто, сообщая нам, когда он начался и закончился.

Однако вместо этого я получаю следующее:

Deleting Columns...
ApiError: No such object: <file> at at Object.parseHttpRespMessage(......)
finished with status: 'crash'

Что нежелательно по понятным причинам. Моя следующая мысль - убедиться, что файл не был удален другим экземпляром скрипта на полпути, но для этого мне нужно будет проверить, используется ли файл другим потоком, то есть моим знание, невозможно.

Есть какие-нибудь идеи?


person skeetman    schedule 25.06.2019    source источник
comment
Измените вопрос, чтобы показать всю функцию, включая создание объекта в облачном хранилище, чтобы мы все могли точно видеть, что здесь происходит.   -  person Doug Stevenson    schedule 25.06.2019
comment
Отредактировано. Теперь код содержит весь сценарий.   -  person skeetman    schedule 26.06.2019
comment
Какой журнал консоли, по вашему мнению, доказывает, что файл существует?   -  person Doug Stevenson    schedule 26.06.2019
comment
У меня был один прямо под журналом «удаление столбцов», но я удалил его после того, как доказал, что файл существует. Добавлю обратно.   -  person skeetman    schedule 26.06.2019
comment
Эта строка журнала не доказывает, что файл существует. Все, что он вам говорит, это то, что вы создали объект File, который указывает на объект, независимо от того, существует он еще или нет. Я предполагаю, что вашего файла на самом деле просто не существует, как следует из сообщения об ошибке.   -  person Doug Stevenson    schedule 26.06.2019
comment
О, я вижу! Я думал, что он возвращает сам объект, когда он просто возвращает указатель, который указывает, где он будет, даже если он находится в процессе создания. Исправление заключается в том, чтобы затем иметь разрешение внутри обратного вызова функции копирования, чтобы убедиться, что w-файл закончил копирование, прежде чем двигаться дальше. Огромное спасибо!   -  person skeetman    schedule 26.06.2019


Ответы (1)


Когда я создавал файл, я вызвал асинхронную функцию copy () и двинулся дальше, что означает, что при попытке доступа к файлу копирование не было завершено. Мне неизвестно, File Object является ссылочной переменной и фактически не содержит самого файла. Пока файл копировался, указатель присутствовал, но указывал на незаконченный файл.

Таким образом, «Нет такого объекта». Чтобы исправить это, я просто использовал обратный вызов, чтобы убедиться, что копирование было завершено, прежде чем я получил доступ к файлу.

Спасибо Дагу Стивенсону за то, что сообщил мне об указателе!

person skeetman    schedule 28.06.2019