0

I have a state machine where i'm doing transitions to move from one state to another. (e.g ReserveState -> StartState)

on this particular case, I have a transition from a ReserveFailedVMState to ReserveVMState

code for ReserveFailedVMState:

const { AbstractVMCtrlState } = require("./AbstractVMCtrlState");
const { ReserveVMState } = require("./ReserveVMState");
const { TerminateDuringReservationState } = require("./TerminateDuringReservationState");
const { ResourceUnavailableState } = require("./ResourceUnavailableState");

//>>>> don't change the CUSTOM CODE comments, if you do generation will overwrite your code >>>>
//###START_CUSTOMCODE1
const { Config } = require("../config/Config");
const { Tasker } = require("../libs/tasker/src/Tasker");
//###END_CUSTOMCODE1
class ReserveVMFailedState extends AbstractVMCtrlState {
  //>>>> don't change the CUSTOM CODE comments, if you do generation will overwrite your code >>>>
  //###START_CUSTOMCODE2
  async onEnterState() {
    //TODO: try to remove the reservation, if exists
    this.logMsg("Could not reserve a VM");
    const config = Config.getConfig();
    if (this.SM.getQueueReservationRetries() <= config.queueReservation.requeueReservationMaxRetries) {
      this.logMsg("Retrying queue for Starting a Reservation, attempt # " + this.SM.getQueueReservationRetries());
      this.SM.setIncreaseQueueReservationRetries();
      await this.retryReserveVMCloudTask();
    } else {
      this.logMsg("After maxRetries, reservation could not be done");
      await this.SM.resourceUnavailable();
    }
  }

  // kicking off a cloud task for retrying to reserve a VM
  async retryReserveVMCloudTask() {
    const run_id = this.getRunId();
    const tasker = new Tasker();
    const vmStartTaskId = await tasker.sendRetryReserveVM(run_id);
    this.SM.setVmStartTaskId(vmStartTaskId);
  }
  //###END_CUSTOMCODE2

  constructor() {
    super();
  }

  async onExitState() {}

  reserveVM() {
    this.logMsg("holaaaaa");
    return new ReserveVMState();
  }

  terminateRequested() {
    return new TerminateDuringReservationState();
  }

  resourceUnavailable() {
    return new ResourceUnavailableState();
  }
}

const serialijse = require("serialijse");
serialijse.declarePersistable(ReserveVMFailedState);

module.exports = { ReserveVMFailedState };

where retryReserveVMCloudTask function kicks a for a transition to move again to ReserveVMState

code for ReserveVMState:

const { AbstractVMCtrlState } = require("./AbstractVMCtrlState");
const { WaitForReservationReadyState } = require("./WaitForReservationReadyState");
const { TerminateDuringReservationState } = require("./TerminateDuringReservationState");
const { ReserveVMFailedState } = require("./ReserveVMFailedState");

//>>>> don't change the CUSTOM CODE comments, if you do generation will overwrite your code >>>>
//###START_CUSTOMCODE1
const { reserveVM } = require("./vm-reservation/reserveVM");
//###END_CUSTOMCODE1
class ReserveVMState extends AbstractVMCtrlState {
  //>>>> don't change the CUSTOM CODE comments, if you do generation will overwrite your code >>>>
  //###START_CUSTOMCODE2
  async onEnterState() {
    // todo later djs fix retries and allow to try on other zones
    this.SM.setCurrentVMZone("europe-west4-b");

    // queue a VM reservation on the GPC cloud
    const run_id = this.getRunId();
    const vmZone = this.SM.getCurrentVMZone();
    const resName = this.getReservationName();

    
    try {
      await reserveVM(run_id, resName, vmZone, "gcp", this.logMsg);
      this.logMsg(`Reservation successful: ${resName} `);
      await this.SM.waitForReservationReady();
    } catch (e) {
      console.error(JSON.stringify(e));
      this.logMsg(`Reserve VM exception:  ${e.name}:  ${e.message}`);
      await this.SM.reserveVMFailed();
    }
  }
  //###END_CUSTOMCODE2
  
    constructor() {
    super();
  }

    
  async onExitState() {
    
  }
  
  waitForReservationReady() {
    return new WaitForReservationReadyState();
  }
  
  terminateRequested() {
    return new TerminateDuringReservationState();
  }
  
  reserveVMFailed() {
    return new ReserveVMFailedState();
  }
  
}

const serialijse = require("serialijse");
serialijse.declarePersistable(ReserveVMState);

module.exports = { ReserveVMState };

i have a logger implemented and when i'm trying this transition i'm getting the following error:

[OSM] 5f64cae6df60d0c4734aa87b - OSM exception: TypeError: ReserveVMState is not a constructor

I have tried different approaches but none seem to be working, what am i missing here?

Thanks in advance

alep007
  • 23
  • 3
  • 3
    What happens if you `console.log(ReserveVMState)` ? – Ruan Mendes Sep 18 '20 at 15:22
  • On my ReserveVMFailedState class, it's undefined!, interesting thing is that i'm using the same reference on a previous transition and console.log throws is a function.[Function: ReserveVMState] – alep007 Sep 18 '20 at 15:47

1 Answers1

0

With the hint on the console.log, I realized that my ReserveVMState was undefined, which was kinda weird. After doing an investigation, the problem was due to NodeJs "require", node.js require() cache - possible to invalidate? I used this link as help and my final solution was changing the "require" on ReserveVMFailedState to this

const { ReserveVMState } = requireUncached("./ReserveVMState");

requireUncached function is provided on the link above.

alep007
  • 23
  • 3