Skip to content

Back end code architecture and documentation

StevenBucaille edited this page Aug 6, 2019 · 4 revisions

In this part, we will add documentation about back-end part of the tool, which contains Master and Slaves, these following will be documented :

  • Overall code architecture description
  • The presentation of the APIStatus file
  • The Master-Slave Socket connection protocol
  • The Master event sequence at startup
  • The relations with front-end
  • The code fragments

Documentation

The back-end runs on NodeJS, an HTTP Server which contains an Express Application handling all endpoints and a Socket Server handling all real-time messages.

There are not many endpoints and socket events but enough to make Slaves and front-end working as the tool should.

Master startup protocol

When launched, there is a sequence of event occurring before the service is accessible :

  1. In case of crash/reboot instead of an initial boot, it is necessary to restore the state of Slaves and data used before this crash/reboot. The Master gather all the informations it was supposed to be aware of before its crash/restart in the APIStatus file which will be explained in the next part, but the main information would be :
  • All API’s being tested, so it needs to gather informations about these API’s such as its general infos (name, etc)
  • the Slaves currently testing an API and their state in the process of testing, so it needs to allow the Socket reconnection of these Slaves (explained below).
  1. Creation a new Express application so as to manage its endpoints for usage and handle requests.
  • It enables CORS (required for Angular usage), the parsing of JSON in requests, etc…
  • It creates all endpoints (see below for endpoints explanations)
  1. Embodiment of this created Express application in an HTTP Server.
  2. Creation of the socket server, with the HTTP Server, which, on connection, discriminates two type of connection :
  • WebClient : Create a necessary connection which is necessary for Front-End Angular work.
  • SlaveClient : Allow connection based on the name of the Slave.
  1. Start the HTTP Server.

APIStatus file

The APIStatus file is the center of the tool, this is where all API's to be tested, results of test of these API's, etc...
This file is a list of these API. An API, in this context, is a dynamic object describing a real API and the progress of its testing.

An API is described as follows :

  • A name, which is simple the baseUrl of the OpenAPI Specification file sent.
  • A list of HTTP requests to be tested, which come directly from the list of operations present in the OpenAPI file
  • The list of servers which are testing the API
  • The results of Uptime tests.
  • The OpenAPI Test Configuration
  • The current progress of test which is the number of steps done since the beginning of the test, and its total progress which is the total number of steps.

HTTP Request Objects

As said, it's a dynamic object, it is initialized with the sending of an OpenAPI Specification file from the User, from this file, a Parser will be used in order to retrieve all the operations, and transform these as HTTP requests objects used by HTTP Request Sending libraries.
The transformation looks like this figure :

This is an OpenAPI Specification described operation :

"/pet": {
  "post": {
    "tags": [
      "pet"
    ],
    "summary": "Add a new pet to the store",
    "description": "",
    "operationId": "addPet",
    "consumes": [
      "application/json",
      "application/xml"
    ],
    "produces": [
      "application/xml",
      "application/json"
    ],
    "parameters": [
      {
        "in": "body",
        "name": "body",
        "description": "Pet object that needs to be added to the store",
        "required": true,
        "schema": {
          "$ref": "#/definitions/Pet"
        }
      }
    ],
    "responses": {
      "405": {
        "description": "Invalid input"
      }
    },
    "security": [
      {
        "petstore_auth": [
          "write:pets",
          "read:pets"
        ]
      }
    ]
  },
}

This is the corresponding HTTP Request object :

{
  "operationId": "addPet",
  "method": "post",
  "headers": {
    "Content-Type": "application/json"
  },
  "params": {},
  "url": "https://petstore.swagger.io/v2/pet",
  "data": {
    "id": 0,
    "category": {
      "id": 0,
      "name": "string"
    },
    "name": "doggie",
    "photoUrls": [
      "string"
    ],
    "tags": [
      {
        "id": 0,
        "name": "string"
      }
    ],
    "status": "available"
  },
  "testResults": {
    "api-0-asia-northeast1-b-latency": {
      "latencyRecords": [
        {
          "date": "2019-07-12T01:15:08.489+02:00",
          "error": false,
          "code": "500",
          "latencyMs": 511.2
        },
        {
          "date": "2019-07-13T07:21:03.747+02:00",
          "error": false,
          "code": "500",
          "latencyMs": 1061.8
        },
        {
          "date": "2019-07-13T17:18:06.078+02:00",
          "error": false,
          "code": "500",
          "latencyMs": 850.1
        }
      ],
      "totalTest": 3,
      "avgSuccess": 0.3333333333333333,
      "meanLatency": "807.70",
      "success": 0
    }
  }
}

During the transformation, there is a determination of the parameters, we give value on the parameters we will use in the testing. This is dependent to the OpenAPITestConfiguration's parameter definition strategy (see OpenAPI Extension Proposal).
These HTTP Requests objects are also dynamic, as the process of testing progresses, it will be aggregated by Latency records.

List of servers

This is the list of servers currently online and testing the API.
A Server gather all information in order to understand the current state of a Slave, to communicate with the cloud service provider, to see its progress in the process of testing the API. See below an example :

{
  "name": "api-0-asia-northeast1-b-latency",
  "testType": "latency",
  "executionType": "masterHandled",
  "region": "asia-northeast1",
  "zone": "asia-northeast1-b",
  "location": "Tokyo, Japan",
  "status": "Test failed, please delete this configuration and create a new one.",
  "state": "testing",
  "substate": "waiting",
  "progress": 51,
  "totalProgress": 8500,
  "repetitionsRemaining": 497
}

Test results

The test results are all the records measured by the Slaves, the Uptime results are located at the root of the API object, as in the OpenAPI Extension Proposal. The Latency results are located in each HTTP Request object they belong to.

OpenAPITestConfiguration

This is directly linked to the OpenAPI Extension Proposal. The only difference if this one is that this is what directly comes from the Angular application :

"testConfig": {
  "latency": {
    "repetitions": 1000,
    "interval": {
      "iso8601format": "PT1H"
    },
    "dp-hours": "01",
    "timeoutThreshold": 10000,
    "zones": [
      "asia-east2",
      "asia-northeast2",
      "europe-west4"
    ],
    "parameterDefinitionStrategy": "provided"
  },
  "uptime": {
    "repetitions": 5000,
    "interval": {
      "iso8601format": "PT10M"
    },
    "dp-minutes": "010",
    "zones": [
      "europe-north1",
      "europe-west2",
      "us-east4"
    ],
    "timeoutThreshold": 10000
  }
}

This object is transformed before the export.

Master-Slave connection protocol

The Master-Slave protocol ensure reliability in the Socket connection between those two actors, the Master and the Slave.

This is directly linked to the notion of State and Substate of a Slave. But there are two case of study for this protocol :

  1. In a usual case, the Master runs, and a Slave is being created and tests an API. This case has already been seen in the What is a Slave section.
  2. When the Master crashes and proceeds to a reboot.
  3. When a SlaveHandled Slave crashes and has to reboot. This part needs to be finished.

Master crashes

During its execution, the Master keeps in memory the state of every Slaves. When the Master crashes, the Socket connection between the two is lost, resulting in a Slave trying to reconnect indefinitely while continuing its test process. When a record occur, the Slave directly sends the result to the Master, if it is disconnected, it will store the result in cache and continue its testing.

Once the Master is back up online, it reads again all the APIStatus file, restoring all Slaves with each state and add each one to a 'disconnected slaves' Map. The Socket Server is turn back on, the Slave trying to reconnect since disconnection finally connects to the Master. The Master, because the Slave is part of 'disconnected slaves', at the connection, send the 'reconnection' event to the Slave. When receiving a 'reconnection' event, the Slave searching in its cache for unsent results and send all of them sequentially. From there, everything is back normal.

Here is a figure explaining the sequential events of this case :

Code content and functions

Master folder

In overall, the tool manages a list of API’s to be tested, display these in a dashboard while testing it in background, then allow the export of these results to the User. The Master program is composed of :

  • The APIStatus folder which contains :
  • The APIStatus.json file which contains all current tested API’s data.
    • The functions used to access or edit these data.
  • The ExpressManagement folder which contains :
    • The public folder contains the Angular compiled application.
    • expressCreation is the file containing all the functions used for the Master start up.
    • expressEndpoint.js is the file managing the express endpoints. For example, the behavior of the ‘/OpenAPI’ endpoint is described in this file.
  • The GoogleCloudManagement folder which contains :
    • The functions to interact with Google Cloud Platform API for instance creation and management.
    • The GCPKeyFile.json file which contains all the private keys to use the GCP API.
    • The regionList.json file which lists all the datacenters of GCP with the location, region and zone names.
  • The Parsers folder which contains :
    • The OpenAPI JSON parser for parsing JSON OpenAPI Specifications file. This parser transforms all API’s operation into an HTTP Request Object, necessary for the tests which gathers method, parameters, headers information.
    • The PetStore parser, which does the same as OpenAPI JSON parser, but has hardcoded parameters value, for development purposes (as for FakeAPIParser).
  • The SocketServerManagement folder which contains :
    • socketServerCreation.js which gathers the server creation and the ‘on client connection’ discrimination (WebClient and SlaveClient, explained later).
    • socketServerSlaveManagement.js which contains all functions managing the Slave connection events (to be explained in a specific part)
    • socketServerWebClientManagement.js which contains all functions managing the WebClient connection events :
      • APIStatus : Send the APIStatus data to the client
      • deleteAPI : Delete the API and all the Slaves currently testing it
      • openApiTestConfig : Receive a new OpenAPI Test Configuration, store it, create the Slaves and wait them to connect.

Slave folder

The Slave program is, briefly, the program which connects to the Master, waits for test information, execute the tests, and then shuts down.
For the first version of the OpenAPI Extension Proposal, only two non-functional properties are tested : Latency and Uptime.

Here is a description of these two type of test.

Latency test

The Latency test, according to the OpenAPI Extension Proposal, is the calculation of the time between the sending of a request to a certain operation and the return of the response.
The Slave will test the Latency of an API by requesting sequentially all its operations with the parameters and data decided by the Master. In fact, the Slave just get an object ready to be used by the HTTP NodeJS library.

Uptime test

The Uptime test, according to the OpenAPI Extension Proposal, is the determination whether an API is available or not to handle requests. The Slave will test Uptime of an API by sending this OPTIONS request where :

  • The openapihost is the host parameter in the OpenAPI Specification file
  • The openapibasepath is the basePath parameter in the OpenAPI Specification file
OPTIONS / HTTP/1.1
Host: https://openapihost/openapibasepath
Content-Type: application/json; charset=utf-8

If the request gets a response before the timeoutThreshold, then the Slaves send a true value to the Master, false otherwise.

Multiple test

Because of the existence of two execution type (SlaveHandled and MasterHandled slaves), there is a 'single' version of these two tests and a 'multiple' version one.
The 'single' version is simply the previous described test.
The 'multiple' version encompass the 'single' version by launching it the number of time the OpenAPITestConfiguration repetition parameter of the said test indicates it. Between each repetition, a timer is launched for a duration of the interval parameter of the test in the OpenAPITestConfiguration.

One last thing about the testing process

A repetition is the fact of running a 'single' version of a test, but inside a test, there can be multiple records. See below the figure which show the succession of event sent from the Slaves to the Master.

Clone this wiki locally