Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Debugger intermittently continually restarts #124

@paustint

Description

@paustint

I am having an issue with a project where the debugger runs and continually restarts over and over until I can finally click the stop button. I am able to run the application from the command line without any errors and if I do a fresh restart of VSCode, it will usually work as expected the first time the application runs (and on occasion even a couple of additional runs) before the infinite restart loop happens.

Even if a breakpoint stops the program, a restart still occurs while paused.

Repo: https://github.com/paustint/aria-csv-loader

Launch config:

{
  // Use IntelliSense to learn about possible Node.js debug attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "program": "${workspaceRoot}/app.js",
      "cwd": "${workspaceRoot}"
    }
  ]
}

Main portion of application - app.js

It seems to restart within the CSV class called here csv.objToCsv(apiTask.response, null, includeHeader);

require('dotenv').config(); // global params
const _ = require('underscore');
const moment = require('moment');
const path = require('path');
var fs = require('fs');
const EventEmitter = require('events');

const csv = require('./services/csv');
const Aria = require('./services/aria');
const Queue = require('./services/queue');

const ApiTask = require('./models/api-task').ApiTask;
process.stdin.resume();//so the program will not close instantly
class ApiTaskEventEmitter extends EventEmitter {}
// const apiTaskEventEmitter = new ApiTaskEventEmitter();
// Read environment variables
let data = {
  filename: process.env.CSV_FILENAME,
  filepath: path.join(__dirname, 'files', 'input', process.env.CSV_FILENAME),
  outputPath: path.join(__dirname, 'files', 'output', `${moment().format('YYYY-MM-DD_HH.mm.ss')}_${process.env.CSV_FILENAME}`),
  iterations: process.env.ITERATIONS || 1,
  apiName: process.env.API_NAME,
  apiType: process.env.API_TYPE,
  env: process.env.ENV,
  clientNo: process.env.CLIENT_NO,
  authKey: process.env.AUTH_KEY,
  threads: process.env.THREADS || 30,
  printOutputCount: process.env.PRINT_OUTPUT_COUNT || 100,
};

///// Validate input //////
// Exit if any environment variables are not included
if (_.isUndefined(data.filename) ||
    _.isUndefined(data.apiName) ||
    _.isUndefined(data.apiType) ||
    _.isUndefined(data.env) ||
    _.isUndefined(data.clientNo) ||
    _.isUndefined(data.authKey)) {
      console.error('All required variables were not included in .env - Please review README.md for a list of required variables');
      process.exit(1);
}

if(!['core', 'object', 'admintools'].includes(data.apiType)) {
  console.error(`API_TYPE of ${data.apiType} is invalid. valid values are 'core', 'object','admintools'`);
  process.exit(1);
}

let confirmText = `Loading the following data:\n`;
confirmText += `Client: ${data.clientNo}\n`;
confirmText += `Auth Key: ${data.authKey}\n`;
confirmText += `Environment: ${data.env}\n`;
confirmText += `Api Type: ${data.apiType}\n`;
confirmText += `Api: ${data.clientNo}\n`;
confirmText += `Threads: ${data.threads}\n`;
confirmText += `Input File: ${data.filename}\n`;

console.info(confirmText);

/**
 * 
 */
let tasks = [];
let startTime;
let finishTime;
let apiTaskEventEmitter = new ApiTaskEventEmitter();
let isFirst = true;
let allResultsPromises = [];


/**
 * Initialize Aria object
 */
let aria = Aria(data.env, data.clientNo, data.authKey);

/**
 * Initialize queue and output filestream
 */
let queue = Queue(aria, data.threads, data.printOutputCount);

let writeStream = fs.createWriteStream(data.outputPath, {});

/**
 * Initialize Event Handlers
 */

/**
 * Each task emits the respond event after being processed
 */
apiTaskEventEmitter.on('response', (apiTask) => {
  let includeHeader = isFirst;
  let result = csv.objToCsv(apiTask.response, null, includeHeader);
  allResultsPromises.push(result);
  result.then(csvString => {
    writeStream.write(`${csvString}\n`);
  })
  .catch(err => {
    console.error("error writing row ot stream", err);
  });
  isFirst = false;
});

/**
 * If there was a fatal error processing a task, write error information
 */
apiTaskEventEmitter.on('error', (err, apiTask) => {
  err = err || {};
  let writeString = '';
  writeString += `${apiTask.csvRowNum},`;
  writeString += `${apiTask.startTime},`;
  writeString += `${apiTask.finishTime},`;
  writeString += `${apiTask.response._duration},`;
  writeString += `FATAL ERROR: ${err.name} ${err.message}`;
  writeStream.write(`${writeString}\n`);
});

/**
 * Once the .drain method is called from the tasks,
 * the finish event is called. Once all response promises are resolved,
 * then the file stream is closed
 */
apiTaskEventEmitter.on('finish', () => {
  console.log('closing file');
  Promise.all(allResultsPromises)
  .then(() => {
    writeStream.end();
    console.info("Successfully closed file");
    process.exit(0);
  })
  .catch(err => {
    console.error("Error waiting for all writing to finish");
    process.exit(1);
  });
});


/**
 * Callback function called after all items in queue are processed
 */
queue.drain = function() {
  console.info('all items have been processed');
  finishTime = moment();
  console.info('Finish Time', finishTime.format('hh:mm:ss'));
  const duration = finishTime - startTime;
  if(duration > 60000) {
    console.info('TotalTime', `${moment.duration(duration).asMinutes()} minutes` );
  } else {
    console.info('TotalTime', `${moment.duration(duration).asSeconds()} seconds` );
  }
  apiTaskEventEmitter.emit('finish');
};



/**
 * Parse CSV and build task from each row to send to queue for processing
 */
csv.csvToJson(data.filepath)
.then(csvObj => {
  console.info('Starting data load.... please wait');
  startTime = moment();
  console.info('Start Time', startTime.format('hh:mm:ss'));
  let counter = 0;
  for(let i = 0; i < data.iterations; i++) {
    let csvRowNum = 1; // resets for each iterations
    csvObj.forEach(row => {
      tasks.push(new ApiTask({
        apiType: data.apiType,
        apiName: data.apiName,
        csvRowNum: csvRowNum++,
        counter: counter++,
        iteration: i,
        payload: row,
        response: {}
      }, apiTaskEventEmitter));
    });

  }
  queue.push(tasks, (err) => {
 });
})
.catch(err => {
  console.error('Fatal error reading file, exiting', err.message);
  process.exit(1);
});


//do something when app is closing
process.on('exit', exitHandler.bind(null));

//catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null));

//catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null));

function exitHandler(options, err) {
  console.log('Existing application');
  if(!_.isUndefined(writeStream)) {
    try {
      writeStream.end(); // attempt to close write stream
    } catch (ex) {  }
  }
  if (err) console.error(err.stack);
  process.exit();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions