Error Handling in ESW-TS

Errors/Exceptions must be handled in application code because that will help user to make further decisions for controlled user interactions with the UI.

To read more on exception handling, refer this document which gives detailed explanation.

Error Types

Service Error

In TMT Architecture, Service error captures all/most of the Service/Network level errors and exceptions. A runtime error which gets thrown after making Service’s API and gets caught in the Service call’s scaffolding snippet falls into this category.

For example:

Using CommandService to submit a command for a non-existing component will result into LocationNotFound.

LocationNotFoundException is a Service Error, and it would contain following fields:

  • errorType: LocationNotFound
  • message: ‘Could not resolve location matching connection: $non_existent_component_connection’
  • status: 500
  • statusText: Internal Server error

Type definition for Service Error can be found here

Client Side Error

Any runtime error which gets thrown before making Service’s API call falls into this category. The Errors and Exception caught at validation or at data creation time will be thrown before making API calls.

For Example: Prefix has a validation that it cannot have - or space in the componentName field.

Following snippet will result into runtime error : it is a native browser’s Error object with the message field and stacktrace. message field will contain the reason for which the validation failed.

Typescript
sourceconst prefix = new Prefix('ESW', 'filter-wheel')

For the given case it will have the following information.

message: Requirement failed - component name filter-wheel has '-'

Error Handling pattern

The following examples shows how to call Agent Service methods and handle the response SpawnResponse and KillResponse.

This example also illustrates error handling of service specific exception AgentNotFoundException along with the generic errors like TransportError and ArithmeticException.

Exploiting try-catch is an anti-pattern

The example uses try-catch to handle errors and exceptions. Generally those errors/exceptions are handled at UI framework level on boundaries of service calls. This example will be updated once we have frontend framework setup in place.

A function whose responsibility is to handle errors and exceptions:

Typescript
source// common function to handle error scenario's
const handleError = (err: Error) => {
  if (err instanceof ServiceError) {
    // depending on use case, error can be handled on following fields
    //  - err.status      (5XX, 4XX, 3XX)
    //  - err.errorType   (AgentNotFoundException, TransportError, ArithmeticException, NullPointerException, etc)

    // Other fields present in error model
    // err.message : contains the reason which can be used to show on UI
    // err.statusText :  Forbidden , Unauthorised, BadRequest, Not Found, etc.

    switch (err.errorType) {
      case 'AgentNotFoundException':
        console.log(err.message) // Location not found for $agentPrefix
        console.log('do something on getting AgentNotFoundException')
        break
      case 'TransportError':
        console.log(err.statusText)
        console.log('do something on getting TransportError (4XX, 3XX, etc))')
        break
      case 'ArithmeticException':
        console.log(err.statusText) // InternalServerError
        console.log(err.message) // Reason : / by zero
        break
      default:
        throw Error(err.message)
    }
  } else {
    // client side error occurred at validations and operations before making api call to the server
    // for ex: Prefix can throw runtime error if componentName is invalid.
  }
}

Example for spawnSequenceManager method call with error handling looks like following:

Typescript
source// setup
const agentService: AgentService = await AgentService({ tokenFactory })

const agentPrefix = new Prefix('ESW', 'agent1')
const obsModeConfigPath = '/obs-mode.conf'
const sequenceManagerVersion = '1.0.0'

try {
  const spawnResponse: SpawnResponse = await agentService.spawnSequenceManager(
    agentPrefix,
    obsModeConfigPath,
    false,
    sequenceManagerVersion
  )

  // spawn response handling (200 status code)
  switch (spawnResponse._type) {
    case 'Spawned':
      // do something on successful spawn operation
      break
    case 'Failed':
      // do something on failed response
      break
  }
} catch (err) {
  handleError(err as Error)
}