All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gatling.http.action.sse.fsm.WhenConnecting.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/*
 * Copyright 2011-2019 GatlingCorp (https://gatling.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.gatling.http.action.sse.fsm

import io.gatling.commons.stats.{ KO, OK }
import io.gatling.commons.util.Throwables._
import io.gatling.core.action.Action
import io.gatling.core.session.Session
import io.gatling.http.action.sse.SseListener
import io.gatling.http.cache.SslContextSupport
import io.gatling.http.check.sse.SseMessageCheckSequence

import io.netty.handler.codec.http.HttpResponseStatus.SWITCHING_PROTOCOLS

object WhenConnecting {

  val WsConnectSuccessStatusCode = Some(Integer.toString(SWITCHING_PROTOCOLS.code))
}

trait WhenConnecting extends SslContextSupport { this: SseActor =>

  def gotoConnecting(session: Session, next: Either[Action, SetCheck], remainingTries: Int = httpProtocol.wsPart.maxReconnects.getOrElse(0)): State = {

    val listener = new SseListener(self, statsEngine, clock)

    // [fl]
    //
    // [fl]
    val userSslContexts = sslContexts(session)
    httpEngine.executeRequest(connectRequest, session.userId, httpProtocol.enginePart.shareConnections, listener, userSslContexts.map(_.sslContext).orNull, userSslContexts.flatMap(_.alplnSslContext).orNull)

    goto(Connecting) using ConnectingData(session, next, clock.nowMillis, remainingTries)
  }

  private def handleConnectFailure(session: Session, next: Either[Action, SetCheck], connectStart: Long, connectEnd: Long, code: Option[String], reason: String, remainingTries: Int): State = {
    // log connect failure
    val newSession = logResponse(session, connectActionName, connectStart, connectEnd, KO, code, Some(reason))
    val newRemainingTries = remainingTries - 1
    if (newRemainingTries > 0) {
      // try again
      logger.debug(s"Connect failed: $code:$reason, retrying ($newRemainingTries remaining tries)")
      gotoConnecting(newSession, next, newRemainingTries)

    } else {
      val nextAction = next match {
        case Left(n) =>
          // failed to connect
          logger.debug(s"Connect failed: $code:$reason, no remaining tries, going to Crashed state and performing next action")
          n
        case Right(sendFrame) =>
          // failed to reconnect, logging failure to send message
          logger.debug(s"Connect failed: $code:$reason, no remaining tries, going to Crashed state, failing pending Send and performing next action")
          statsEngine.logCrash(newSession, sendFrame.actionName, "Failed to reconnect")
          sendFrame.next
      }
      nextAction ! newSession.markAsFailed
      goto(Crashed) using CrashedData(Some(reason))
    }
  }

  when(Connecting) {
    case Event(SseStreamConnected(stream, connectEnd), ConnectingData(session, next, connectStart, _)) =>
      val sessionWithGroupTimings = logResponse(session, connectActionName, connectStart, connectEnd, OK, WhenConnecting.WsConnectSuccessStatusCode, None)

      connectCheckSequence match {
        case SseMessageCheckSequence(timeout, currentCheck :: remainingChecks) :: remainingCheckSequences =>
          // wait for some checks before proceeding
          logger.debug("Connected, performing checks before proceeding")

          val timeoutId = scheduleTimeout(timeout)
          //[fl]
          //
          //[fl]
          goto(PerformingCheck) using PerformingCheckData(
            stream = stream,
            currentCheck = currentCheck,
            remainingChecks = remainingChecks,
            checkSequenceStart = connectEnd,
            checkSequenceTimeoutId = timeoutId,
            remainingCheckSequences = remainingCheckSequences,
            session = sessionWithGroupTimings,
            next = next
          )

        case _ => // same as Nil as WsFrameCheckSequence#checks can't be Nil, but compiler complains that match may not be exhaustive
          // send next
          next match {
            case Left(nextAction) =>
              logger.debug("Connected, no checks, performing next action")
              nextAction ! sessionWithGroupTimings

            case Right(sendFrame) =>
              logger.debug("Reconnected, no checks, sending pending message")
              self ! sendFrame.copyWithSession(sessionWithGroupTimings)
          }
          goto(Idle) using IdleData(sessionWithGroupTimings, stream)
      }

    case Event(SseStreamClosed(timestamp), ConnectingData(session, next, connectStart, remainingTries)) =>
      // unexpected close
      handleConnectFailure(session, next, connectStart, timestamp, None, "Socket closed", remainingTries)

    case Event(SseStreamCrashed(t, timestamp), ConnectingData(session, next, connectStart, remainingTries)) =>
      // crash
      handleConnectFailure(session, next, connectStart, timestamp, None, t.rootMessage, remainingTries)
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy