GCF "Нет такого объекта", когда рассматриваемый объект был только что создан - PullRequest
0 голосов
/ 25 июня 2019

Я настраиваю функцию 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'

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

Есть идеи?

1 Ответ

0 голосов
/ 28 июня 2019

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

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

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

...