node js не ведет себя одинаково на локальном и Google App Egine

Я разрабатываю приложение для загрузки файла .las в ион цезия.

Я изменил этот код https://github.com/CesiumGS/cesium-ion-rest-api-examples/blob/main/tutorials/rest-api/index.js , чтобы передать файл из браузера.

Он работает безупречно, когда я запускаю npm start в своей локальной среде.

Когда я пытаюсь сделать то же самое в App Engine, я не получаю сообщения о том, где находится процесс. Тем не менее, он загружает файл. Просто я не могу следить за тем, что происходит.

Чтобы объяснить, что происходит ниже, я отправляю файл с клиента, затем он ловитсяapp.post("/upload"Затем он создает ресурс на Ion, а затем загружает его на S3, затем сообщает ion, что все готово, а затем отслеживает тайлинг на Ion. Тогда я звоню каждую секундуapp.post("/progress"Это отправляет статистику клиенту.

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

      const express = require('express');
const app = express();
const port = process.env.PORT || 3001;
const fileUpload = require("express-fileupload");
const cors = require('cors');
var path = require('path');
const AWS = require('aws-sdk');
const fs = require('fs');
const rawdatafr = require('./lang/fr.json');
const rawdataen = require('./lang/en.json');
const axios = require('axios').default;
const accessToken = process.env.REACT_APP_ION_TOKEN;

const environment = process.env.NODE_ENV || 'production';

var urlLang = (environment === 'development') ? 'client/src/lang/' : 'lang/'; 
console.log('urlLang ?  '+urlLang);


app.use(cors());
app.use(fileUpload({
  useTempFiles: true,
  safeFileNames: false,
  preserveExtension: true,
  tempFileDir: 'temp/'
}));
'use strict';

var messageFromLoc = rawdataen;
var input = null;
var filename = null;
var srcType = 'POINT_CLOUD';
var message = null;
var needMonitoring = false;
var assetMetadata = null;
var finished = null;
 
function resetGlobalvar(){
    message = null;
    needMonitoring = false;
    assetMetadata = null;
    finished = null;
    input = null;
    filename = null;
    srcType = 'POINT_CLOUD';
}

async function creat_asset(){
    finished = false;
    message = 'create asset';
    axios.post('https://api.cesium.com/v1/assets', {
        name: filename,
        description: '',
        type: '3DTILES',
        options: {
            position:[ 2.29, 48.85, 0.1],
            sourceType: srcType,
        }
      },{
        headers: { Authorization: `Bearer ${accessToken}` }
      })
      .then(function (response) {
        message = 'created successfully :> send to s3';
        sendtos3(response.data);
      })
      .catch(function (error) {
        console.log(error);
        message = error;
      });
}

async function sendtos3(response){
    console.log('Asset created.');
    message = 'send to s3';
    try{
        const uploadLocation = response.uploadLocation;
        const s3 = new AWS.S3({
            apiVersion: '2006-03-01',
            region: 'us-east-1',
            signatureVersion: 'v4',
            endpoint: uploadLocation.endpoint,
            credentials: new AWS.Credentials(
                uploadLocation.accessKey,
                uploadLocation.secretAccessKey,
                uploadLocation.sessionToken)
        });

        let params =  {
            Body: fs.createReadStream(input),
            Bucket: uploadLocation.bucket,
            Key: uploadLocation.prefix+filename
        };
    
        let s3Response = await s3.upload(params).on('httpUploadProgress', function (progress) {
            message = `${messageFromLoc.upload}: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`;
            console.log(`Upload: ${((progress.loaded / progress.total) * 100).toFixed(2)}%`);
        }).promise();
        // request successed
        console.log(`File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`);
        message = `File uploaded to S3 at ${s3Response.Bucket} bucket. File location: ${s3Response.Location}`;
        step3(response);
        // return s3Response.Location; 
    }
    // request failed
    catch (ex) {
        console.error(ex);
        message = ex;
    }
}
async function step3(response){
    const onComplete = response.onComplete;
    assetMetadata = response.assetMetadata;
    message = 'step3';
    axios.post(onComplete.url, onComplete.fields,{
        headers: { Authorization: `Bearer ${accessToken}` }
      })
      .then(function (response) {
        message = 'step3 done';
        monitorTiling(assetMetadata);
      })
      .catch(function (error) {
        console.log(error);
        message = error;
      });
}

async function monitorTiling(assetMetadata){
    // console.log(response);
    const assetId = assetMetadata.id;
    message = 'monitorTiling';
    axios.get(`https://api.cesium.com/v1/assets/${assetId}`,{headers: { Authorization: `Bearer ${accessToken}` }})
        .then(function (response) {
        // handle success
        console.log('monitorTiling - success');
        var status = response.data.status;
        message = 'Tiling - success';
        if (status === 'COMPLETE') {
            console.log('Asset tiled successfully');
            console.log(`View in ion: https://cesium.com/ion/assets/${assetMetadata.id}`);
            message = 'Asset tiled successfully';
            needMonitoring = false;
            finished = true;
        } else if (status === 'DATA_ERROR') {
            console.log('ion detected a problem with the uploaded data.');
            message = 'ion detected a problem with the uploaded data.';
            needMonitoring = false;
            finished = true;
        } else if (status === 'ERROR') {
            console.log('An unknown tiling error occurred, please contact support@cesium.com.');
            message = 'An unknown tiling error occurred, please contact support@cesium.com.';
            needMonitoring = false;
            finished = true;
        } else {
            needMonitoring = true;
            if (status === 'NOT_STARTED') {
                console.log('Tiling pipeline initializing.');
                message = 'Tiling pipeline initializing.';
            } else { // IN_PROGRESS
                console.log(`Asset is ${assetMetadata.percentComplete}% complete.`);
                message = `Asset is ${assetMetadata.percentComplete}% complete.`;
            }
        }
        })
        .catch(function (error) {
        // handle error
        console.log(error);
        message =error;
        })
}
 
/*------- LISTEN FOR CALL TO UPLOAD AND START THE UPLOAD PROCESS ----------*/
app.post("/upload", (req, res) => {
    if (!req.files) {
        res.send("File was not found");
        message = 'File was not found';
        return;
    }
    input = req.files.file.tempFilePath;
    filename = req.files.file.name;
    emptyTempFolder('temp', input.replace('temp/', ''));
    
    var ext = path.extname(filename);
    if(ext=='.zip'){
        srcType = 'CITYGML';
    }
    /*------- START UPLOAD PROCESS ----------*/
    creat_asset();
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

/*------- LISTEN FOR PROGRESS TO UPLOAD ASSET ----------*/
app.get("/progress", (req, res) => {
    // lang = req.get('Accept-Language').substring(0, 2).toLowerCase();
    // if(lang=='fr'){
    //     messageFromLoc = rawdatafr;
    // }
    console.log('message  ='+message);
    if(needMonitoring){
        monitorTiling(assetMetadata);
    }

    res.json({ message: message, done: finished, myAssetMetadata: assetMetadata });
    if(finished){
        resetGlobalvar();
    }
});

/*--------------STATIC ----------------*/
app.use(express.static( path.join(__dirname, 'build' )));

И мой app.yaml выглядит так:

      runtime: nodejs14
env: standard
includes:
  - env_variables.yaml
instance_class: B1
service: my-app
basic_scaling:
  max_instances: 25
  idle_timeout: 60m

1 ответ

Я думаю, что это из вашего экземпляра (ов). Вы используете базовое масштабирование с количеством экземпляров до 25.

Похоже, что происходит комбинация следующего

а) Когда вы отправляете запрос, создается новый экземпляр вашего приложения, что означает, что все глобальные переменные начинаются со своих значений по умолчанию (начальное значение сообщения равноnull).

б) В других случаях просьба/progressобрабатывается существующим экземпляром, который уже обрабатывал запрос на загрузку, и этот запрос был завершен, поэтому в сообщении говоритсяcompleted

У вас нет этой проблемы в вашей локальной среде, потому что работает только 1 экземпляр.

Чтобы проверить эту теорию, изменитеapp.yamlи установитьmax_instances: 1. Предполагается, что это заставит приложение использовать только 1 экземпляр, что означает, что последующие запросы должны использовать существующий экземпляр (который имеет обновленное состояние ваших глобальных переменных).

Другие вопросы по тегам