This is an automated email from the ASF dual-hosted git repository. markusthoemmes pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push: new a8b75e9 Generate TransactionId in nginx rather than controller. (#3199) a8b75e9 is described below commit a8b75e9871d860406d71bdf5d2c7a534d54c8dc9 Author: Christian Bickel <git...@cbickel.de> AuthorDate: Thu May 3 12:53:10 2018 +0200 Generate TransactionId in nginx rather than controller. (#3199) - Move from a numeric TransactionId to a random string. - Add ability to take a header's value as the TransactionId (like `X-Request-Id`). - Add `X-Request-Id` header from nginx (and return it to the user). --- ansible/group_vars/all | 2 +- ansible/roles/controller/tasks/deploy.yml | 2 +- ansible/roles/invoker/tasks/deploy.yml | 1 + ansible/roles/nginx/templates/nginx.conf.j2 | 8 +- common/scala/src/main/resources/application.conf | 3 +- .../main/scala/whisk/common/TransactionId.scala | 90 +++++++++------------- .../src/main/scala/whisk/core/WhiskConfig.scala | 1 - .../main/scala/whisk/http/BasicHttpService.scala | 51 ++++++++---- .../src/main/scala/whisk/http/ErrorResponse.scala | 2 +- .../scala/whisk/core/controller/Controller.scala | 2 - .../scala/whisk/core/controller/Triggers.scala | 7 +- .../main/scala/whisk/core/invoker/Invoker.scala | 4 +- .../scala/whisk/core/invoker/InvokerServer.scala | 28 ------- .../test/scala/whisk/common/SchedulerTests.scala | 2 +- .../containerpool/test/ContainerProxyTests.scala | 40 ++++------ .../controller/test/ControllerTestCommon.scala | 6 +- .../core/controller/test/PackagesApiTests.scala | 16 ++-- .../core/controller/test/WebActionsApiTests.scala | 2 +- .../scala/whisk/core/database/test/DbUtils.scala | 10 ++- .../core/database/test/DocumentHandlerTests.scala | 24 +++--- .../test/behavior/ArtifactStoreBehaviorBase.scala | 5 +- .../scala/whisk/core/entity/test/SchemaTests.scala | 8 +- 22 files changed, 137 insertions(+), 177 deletions(-) diff --git a/ansible/group_vars/all b/ansible/group_vars/all index f04807b..977d6ed 100644 --- a/ansible/group_vars/all +++ b/ansible/group_vars/all @@ -97,7 +97,7 @@ jmx: enabled: "{{ jmxremote_enabled | default('true') }}" transactions: - stride: "{{ groups['controllers'] | length }}" + header: "{{ transactions_header | default('X-Request-ID') }}" registry: confdir: "{{ config_root_dir }}/registry" diff --git a/ansible/roles/controller/tasks/deploy.yml b/ansible/roles/controller/tasks/deploy.yml index 8173f00..8a839d4 100644 --- a/ansible/roles/controller/tasks/deploy.yml +++ b/ansible/roles/controller/tasks/deploy.yml @@ -201,7 +201,7 @@ "CONFIG_whisk_spi_LoadBalancerProvider": "{{ controller.loadbalancer.spi }}" "CONFIG_logback_log_level": "{{ controller.loglevel }}" - "CONFIG_whisk_transactions_stride": "{{ transactions.stride | default() }}" + "CONFIG_whisk_transactions_header": "{{ transactions.header }}" - name: create seed nodes list set_fact: diff --git a/ansible/roles/invoker/tasks/deploy.yml b/ansible/roles/invoker/tasks/deploy.yml index 2643b54..b542d78 100644 --- a/ansible/roles/invoker/tasks/deploy.yml +++ b/ansible/roles/invoker/tasks/deploy.yml @@ -227,6 +227,7 @@ -e CONFIG_whisk_timeLimit_max='{{ limit_action_time_max | default() }}' -e CONFIG_whisk_timeLimit_std='{{ limit_action_time_std | default() }}' -e CONFIG_whisk_activation_payload_max='{{ limit_activation_payload | default() }}' + -e CONFIG_whisk_transactions_header='{{ transactions.header }}' -v /sys/fs/cgroup:/sys/fs/cgroup -v /run/runc:/run/runc -v {{ whisk_logs_dir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}:/logs diff --git a/ansible/roles/nginx/templates/nginx.conf.j2 b/ansible/roles/nginx/templates/nginx.conf.j2 index 8b2f07b..a8632d9 100644 --- a/ansible/roles/nginx/templates/nginx.conf.j2 +++ b/ansible/roles/nginx/templates/nginx.conf.j2 @@ -15,7 +15,7 @@ http { rewrite_log on; {# change log format to display the upstream information #} log_format combined-upstream '$remote_addr - $remote_user [$time_local] ' - '$request $status $body_bytes_sent ' + '[#tid_$request_id] $request $status $body_bytes_sent ' '$http_referer $http_user_agent $upstream_addr'; access_log /logs/nginx_access.log combined-upstream; @@ -59,6 +59,12 @@ http { } proxy_set_header X-OW-EXTRA-LOGGING $extra_logging; + # Set the request id generated by nginx as tid-header to the upstream. + # This tid is either the request-id generated by ngix or a tid, sent by the caller. + proxy_set_header {{ transactions.header }} $request_id; + + # Send the tid always back as header. + add_header {{ transactions.header }} $request_id always; {# Turn off sending information about the server to the client #} server_tokens off; diff --git a/common/scala/src/main/resources/application.conf b/common/scala/src/main/resources/application.conf index f665edb..ea4bd46 100644 --- a/common/scala/src/main/resources/application.conf +++ b/common/scala/src/main/resources/application.conf @@ -131,8 +131,7 @@ whisk { # transaction ID related configuration transactions { - stride = 1 - stride = ${?CONTROLLER_INSTANCES} + header = "X-Request-ID" } # action runtimes configuration runtimes { diff --git a/common/scala/src/main/scala/whisk/common/TransactionId.scala b/common/scala/src/main/scala/whisk/common/TransactionId.scala index 1f901a1..cb16a42 100644 --- a/common/scala/src/main/scala/whisk/common/TransactionId.scala +++ b/common/scala/src/main/scala/whisk/common/TransactionId.scala @@ -17,20 +17,15 @@ package whisk.common -import java.time.Clock -import java.time.Duration -import java.time.Instant -import java.util.concurrent.atomic.AtomicInteger +import java.time.{Clock, Duration, Instant} -import scala.math.BigDecimal.int2bigDecimal -import scala.util.Try -import akka.event.Logging.{DebugLevel, InfoLevel, WarningLevel} -import akka.event.Logging.LogLevel +import akka.event.Logging.{DebugLevel, InfoLevel, LogLevel, WarningLevel} +import akka.http.scaladsl.model.headers.RawHeader +import pureconfig.loadConfigOrThrow import spray.json._ - import whisk.core.ConfigKeys -import pureconfig._ +import scala.util.Try /** * A transaction id for tracking operations in the system that are specific to a request. @@ -39,11 +34,9 @@ import pureconfig._ */ case class TransactionId private (meta: TransactionMetadata) extends AnyVal { def id = meta.id - override def toString = { - if (meta.id > 0) s"#tid_${meta.id}" - else if (meta.id < 0) s"#sid_${-meta.id}" - else "??" - } + override def toString = s"#tid_${meta.id}" + + def toHeader = RawHeader(TransactionId.generatorConfig.header, meta.id) /** * Method to count events. @@ -190,8 +183,9 @@ case class StartMarker(val start: Instant, startMarker: LogMarkerToken) * @param id the transaction identifier; it is positive for client requests, * negative for system operation and zero when originator is not known * @param start the timestamp when the request processing commenced + * @param extraLogging enables logging, if set to true */ -protected case class TransactionMetadata(val id: Long, val start: Instant, val extraLogging: Boolean = false) +protected case class TransactionMetadata(val id: String, val start: Instant, val extraLogging: Boolean = false) object TransactionId { @@ -200,58 +194,44 @@ object TransactionId { val metricsKamonTags: Boolean = sys.env.get("METRICS_KAMON_TAGS").getOrElse("False").toBoolean val metricsLog: Boolean = sys.env.get("METRICS_LOG").getOrElse("True").toBoolean - val unknown = TransactionId(0) - val testing = TransactionId(-1) // Common id for for unit testing - val invoker = TransactionId(-100) // Invoker startup/shutdown or GC activity - val invokerWarmup = TransactionId(-101) // Invoker warmup thread that makes stem-cell containers - val invokerNanny = TransactionId(-102) // Invoker nanny thread - val dispatcher = TransactionId(-110) // Kafka message dispatcher - val loadbalancer = TransactionId(-120) // Loadbalancer thread - val invokerHealth = TransactionId(-121) // Invoker supervision - val controller = TransactionId(-130) // Controller startup - val dbBatcher = TransactionId(-140) // Database batcher - - def apply(tid: BigDecimal, extraLogging: Boolean = false): TransactionId = { - Try { - val now = Instant.now(Clock.systemUTC()) - TransactionId(TransactionMetadata(tid.toLong, now, extraLogging)) - } getOrElse unknown + val generatorConfig = loadConfigOrThrow[TransactionGeneratorConfig](ConfigKeys.transactions) + + val systemPrefix = "sid_" + + val unknown = TransactionId(systemPrefix + "unknown") + val testing = TransactionId(systemPrefix + "testing") // Common id for for unit testing + val invoker = TransactionId(systemPrefix + "invoker") // Invoker startup/shutdown or GC activity + val invokerWarmup = TransactionId(systemPrefix + "invokerWarmup") // Invoker warmup thread that makes stem-cell containers + val invokerNanny = TransactionId(systemPrefix + "invokerNanny") // Invoker nanny thread + val dispatcher = TransactionId(systemPrefix + "dispatcher") // Kafka message dispatcher + val loadbalancer = TransactionId(systemPrefix + "loadbalancer") // Loadbalancer thread + val invokerHealth = TransactionId(systemPrefix + "invokerHealth") // Invoker supervision + val controller = TransactionId(systemPrefix + "controller") // Controller startup + val dbBatcher = TransactionId(systemPrefix + "dbBatcher") // Database batcher + + def apply(tid: String, extraLogging: Boolean = false): TransactionId = { + val now = Instant.now(Clock.systemUTC()) + TransactionId(TransactionMetadata(tid, now, extraLogging)) } implicit val serdes = new RootJsonFormat[TransactionId] { def write(t: TransactionId) = { if (t.meta.extraLogging) - JsArray(JsNumber(t.meta.id), JsNumber(t.meta.start.toEpochMilli), JsBoolean(t.meta.extraLogging)) + JsArray(JsString(t.meta.id), JsNumber(t.meta.start.toEpochMilli), JsBoolean(t.meta.extraLogging)) else - JsArray(JsNumber(t.meta.id), JsNumber(t.meta.start.toEpochMilli)) + JsArray(JsString(t.meta.id), JsNumber(t.meta.start.toEpochMilli)) } def read(value: JsValue) = Try { value match { - case JsArray(Vector(JsNumber(id), JsNumber(start))) => - TransactionId(TransactionMetadata(id.longValue, Instant.ofEpochMilli(start.longValue), false)) - case JsArray(Vector(JsNumber(id), JsNumber(start), JsBoolean(extraLogging))) => - TransactionId(TransactionMetadata(id.longValue, Instant.ofEpochMilli(start.longValue), extraLogging)) + case JsArray(Vector(JsString(id), JsNumber(start))) => + TransactionId(TransactionMetadata(id, Instant.ofEpochMilli(start.longValue), false)) + case JsArray(Vector(JsString(id), JsNumber(start), JsBoolean(extraLogging))) => + TransactionId(TransactionMetadata(id, Instant.ofEpochMilli(start.longValue), extraLogging)) } } getOrElse unknown } } -/** - * A thread-safe transaction counter. - */ -trait TransactionCounter { - case class TransactionCounterConfig(stride: Int) - - val transCounterConfig = loadConfigOrThrow[TransactionCounterConfig](ConfigKeys.transactions) - val stride = transCounterConfig.stride - val instanceOrdinal: Int - - // seed the counter so transids do not overlap: instanceOrdinal + n * stride, start at n = 1 - private lazy val cnt = new AtomicInteger(instanceOrdinal + stride) - - def transid(extraLogging: Boolean = false): TransactionId = { - TransactionId(cnt.addAndGet(stride), extraLogging) - } -} +case class TransactionGeneratorConfig(header: String) diff --git a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala index 231341f..0c937ae 100644 --- a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala +++ b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala @@ -240,7 +240,6 @@ object ConfigKeys { val kubernetesTimeouts = s"$kubernetes.timeouts" val transactions = "whisk.transactions" - val stride = s"$transactions.stride" val logStore = "whisk.logstore" val splunk = s"$logStore.splunk" diff --git a/common/scala/src/main/scala/whisk/http/BasicHttpService.scala b/common/scala/src/main/scala/whisk/http/BasicHttpService.scala index ece541b..586d7dc 100644 --- a/common/scala/src/main/scala/whisk/http/BasicHttpService.scala +++ b/common/scala/src/main/scala/whisk/http/BasicHttpService.scala @@ -17,27 +17,29 @@ package whisk.http -import scala.collection.immutable.Seq -import scala.concurrent.{Await, Future} -import scala.concurrent.duration.DurationInt +import java.util.concurrent.ThreadLocalRandom + import akka.actor.ActorSystem import akka.event.Logging import akka.http.scaladsl.Http -import akka.http.scaladsl.model._ -import akka.http.scaladsl.model.HttpRequest -import akka.http.scaladsl.server._ +import akka.http.scaladsl.model.{HttpRequest, _} import akka.http.scaladsl.server.RouteResult.Rejected +import akka.http.scaladsl.server._ import akka.http.scaladsl.server.directives._ import akka.stream.ActorMaterializer import spray.json._ import whisk.common._ import whisk.core.WhiskConfig +import scala.collection.immutable.Seq +import scala.concurrent.duration.DurationInt +import scala.concurrent.{Await, Future} + /** * This trait extends the Akka Directives and Actor with logging and transaction counting * facilities common to all OpenWhisk REST services. */ -trait BasicHttpService extends Directives with TransactionCounter { +trait BasicHttpService extends Directives { val OW_EXTRA_LOGGING_HEADER = "X-OW-EXTRA-LOGGING" @@ -72,13 +74,15 @@ trait BasicHttpService extends Directives with TransactionCounter { */ def route: Route = { assignId { implicit transid => - DebuggingDirectives.logRequest(logRequestInfo _) { - DebuggingDirectives.logRequestResult(logResponseInfo _) { - BasicDirectives.mapRequest(_.removeHeader(OW_EXTRA_LOGGING_HEADER)) { - handleRejections(BasicHttpService.customRejectionHandler) { - prioritizeRejections { - toStrictEntity(30.seconds) { - routes + respondWithHeader(transid.toHeader) { + DebuggingDirectives.logRequest(logRequestInfo _) { + DebuggingDirectives.logRequestResult(logResponseInfo _) { + BasicDirectives.mapRequest(_.removeHeader(OW_EXTRA_LOGGING_HEADER)) { + handleRejections(BasicHttpService.customRejectionHandler) { + prioritizeRejections { + toStrictEntity(30.seconds) { + routes + } } } } @@ -88,6 +92,10 @@ trait BasicHttpService extends Directives with TransactionCounter { } } + // Scala random should be enough here, as the generation for the tid is only a fallback. In addition the tid only has + // to be unique within a few minutes. + private val dict = ('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') + /** Assigns transaction id to every request. */ protected def assignId = HeaderDirectives.optionalHeaderValueByName(OW_EXTRA_LOGGING_HEADER) flatMap { headerValue => val extraLogging = headerValue match { @@ -97,7 +105,20 @@ trait BasicHttpService extends Directives with TransactionCounter { case Some(value) => value.toLowerCase == "on" case None => false } - extract(_ => transid(extraLogging)) + extract { req => + val tid = + req.request.headers + .find(_.name == TransactionId.generatorConfig.header) + .map(_.value) + .filterNot(_.startsWith(TransactionId.systemPrefix)) + .getOrElse { + // As this is only a fallback, because the tid should be generated by nginx, this shouldn't be used. + // Therefore we didn't take a deep look into performance here. + (0 until 32).map(_ => dict(ThreadLocalRandom.current().nextInt(dict.size))).mkString("") + } + + TransactionId(tid, extraLogging) + } } /** Generates log entry for every request. */ diff --git a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala index 97d2008..40685c0 100644 --- a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala +++ b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala @@ -253,7 +253,7 @@ object ErrorResponse extends Directives with DefaultJsonProtocol { def read(v: JsValue) = Try { v.asJsObject.getFields("error", "code") match { - case Seq(JsString(error), JsNumber(code)) => + case Seq(JsString(error), JsString(code)) => ErrorResponse(error, TransactionId(code)) case Seq(JsString(error)) => ErrorResponse(error, TransactionId.unknown) diff --git a/core/controller/src/main/scala/whisk/core/controller/Controller.scala b/core/controller/src/main/scala/whisk/core/controller/Controller.scala index 340df96..c1c7390 100644 --- a/core/controller/src/main/scala/whisk/core/controller/Controller.scala +++ b/core/controller/src/main/scala/whisk/core/controller/Controller.scala @@ -82,8 +82,6 @@ class Controller(val instance: InstanceId, implicit val logging: Logging) extends BasicRasService { - override val instanceOrdinal = instance.toInt - TransactionId.controller.mark( this, LoggingMarkers.CONTROLLER_STARTUP(instance.toInt), diff --git a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala index 8bf2de7..760ae04 100644 --- a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala +++ b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala @@ -383,7 +383,8 @@ trait WhiskTriggersApi extends WhiskCollectionAPI { * @param args the arguments to post to the action * @return a future with the HTTP response from the action activation */ - private def postActivation(user: Identity, rule: ReducedRule, args: JsObject): Future[HttpResponse] = { + private def postActivation(user: Identity, rule: ReducedRule, args: JsObject)( + implicit transid: TransactionId): Future[HttpResponse] = { // Build the url to invoke an action mapped to the rule val actionUrl = baseControllerPath / rule.action.path.root.asString / "actions" @@ -394,7 +395,9 @@ trait WhiskTriggersApi extends WhiskCollectionAPI { val request = HttpRequest( method = POST, uri = url.withPath(actionUrl ++ actionPath), - headers = List(Authorization(BasicHttpCredentials(user.authkey.uuid.asString, user.authkey.key.asString))), + headers = List( + Authorization(BasicHttpCredentials(user.authkey.uuid.asString, user.authkey.key.asString)), + transid.toHeader), entity = HttpEntity(MediaTypes.`application/json`, args.compactPrint)) singleRequest(request) diff --git a/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala b/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala index 58a4d1d..4a69d3c 100644 --- a/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala +++ b/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala @@ -39,7 +39,7 @@ import whisk.core.connector.PingMessage import whisk.core.entity._ import whisk.core.entity.ExecManifest import whisk.core.entity.InstanceId -import whisk.http.BasicHttpService +import whisk.http.{BasicHttpService, BasicRasService} import whisk.spi.SpiLoader import whisk.utils.ExecutionContextFactory import whisk.common.TransactionId @@ -185,7 +185,7 @@ object Invoker { }) val port = config.servicePort.toInt - BasicHttpService.startHttpService(new InvokerServer().route, port)( + BasicHttpService.startHttpService(new BasicRasService {}.route, port)( actorSystem, ActorMaterializer.create(actorSystem)) } diff --git a/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala b/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala deleted file mode 100644 index 2b45fca..0000000 --- a/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 whisk.core.invoker - -import whisk.http.BasicRasService - -/** - * Implements web server to handle certain REST API calls. - * Currently provides a health ping route, only. - */ -class InvokerServer() extends BasicRasService { - override val instanceOrdinal = 1 -} diff --git a/tests/src/test/scala/whisk/common/SchedulerTests.scala b/tests/src/test/scala/whisk/common/SchedulerTests.scala index 14d325b..35eaf68 100644 --- a/tests/src/test/scala/whisk/common/SchedulerTests.scala +++ b/tests/src/test/scala/whisk/common/SchedulerTests.scala @@ -127,7 +127,7 @@ class SchedulerTests extends FlatSpec with Matchers with WskActorSystem with Str waitForCalls() stream.toString.split(" ").drop(1).mkString(" ") shouldBe { - s"[ERROR] [#sid_1] [Scheduler] halted because $msg\n" + s"[ERROR] [$transid] [Scheduler] halted because $msg\n" } } diff --git a/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala b/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala index fcde7e7..205834e 100644 --- a/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala @@ -19,41 +19,29 @@ package whisk.core.containerpool.test import java.time.Instant -import scala.concurrent.Future -import scala.concurrent.Promise -import scala.concurrent.duration._ -import org.junit.runner.RunWith -import org.scalatest.BeforeAndAfterAll -import org.scalatest.FlatSpecLike -import org.scalatest.Matchers -import org.scalatest.junit.JUnitRunner -import akka.actor.ActorRef -import akka.actor.ActorSystem -import akka.actor.FSM -import akka.actor.FSM.CurrentState -import akka.actor.FSM.SubscribeTransitionCallBack -import akka.actor.FSM.Transition +import akka.actor.FSM.{CurrentState, SubscribeTransitionCallBack, Transition} +import akka.actor.{ActorRef, ActorSystem, FSM} import akka.stream.scaladsl.Source -import akka.testkit.ImplicitSender -import akka.testkit.TestKit +import akka.testkit.{ImplicitSender, TestKit} import akka.util.ByteString -import common.LoggedFunction -import common.StreamLogging - -import scala.concurrent.ExecutionContext -import spray.json._ +import common.{LoggedFunction, StreamLogging} +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers} import spray.json.DefaultJsonProtocol._ -import whisk.common.Logging -import whisk.common.TransactionId +import spray.json._ +import whisk.common.{Logging, TransactionId} import whisk.core.connector.ActivationMessage import whisk.core.containerpool._ import whisk.core.containerpool.logging.LogCollectingException +import whisk.core.entity.ExecManifest.{ImageName, RuntimeManifest} import whisk.core.entity._ -import whisk.core.entity.ExecManifest.RuntimeManifest -import whisk.core.entity.ExecManifest.ImageName import whisk.core.entity.size._ import whisk.http.Messages +import scala.concurrent.duration._ +import scala.concurrent.{ExecutionContext, Future, Promise} + @RunWith(classOf[JUnitRunner]) class ContainerProxyTests extends TestKit(ActorSystem("ContainerProxys")) @@ -79,7 +67,7 @@ class ContainerProxyTests val action = ExecutableWhiskAction(EntityPath("actionSpace"), EntityName("actionName"), exec) // create a transaction id to set the start time and control queue time - val messageTransId = TransactionId(BigDecimal(TransactionId.testing.meta.id)) + val messageTransId = TransactionId(TransactionId.testing.meta.id) val initInterval = { val now = messageTransId.meta.start.plusMillis(50) // this is the queue time for cold start diff --git a/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala b/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala index e9df1d5..fdceb14 100644 --- a/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala +++ b/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala @@ -30,7 +30,6 @@ import akka.http.scaladsl.testkit.ScalatestRouteTest import akka.http.scaladsl.testkit.RouteTestTimeout import spray.json.DefaultJsonProtocol import spray.json.JsString -import whisk.common.TransactionCounter import whisk.common.TransactionId import whisk.core.WhiskConfig import whisk.core.connector.ActivationMessage @@ -52,15 +51,12 @@ protected trait ControllerTestCommon with BeforeAndAfterAll with ScalatestRouteTest with Matchers - with TransactionCounter with DbUtils with ExecHelpers with WhiskServices with StreamLogging { - override val instanceOrdinal = 0 - override val instance = InstanceId(instanceOrdinal) - val activeAckTopicIndex = InstanceId(instanceOrdinal) + val activeAckTopicIndex = InstanceId(0) implicit val routeTestTimeout = RouteTestTimeout(90 seconds) diff --git a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala index c0e2e40..706ca9c 100644 --- a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala @@ -17,19 +17,19 @@ package whisk.core.controller.test -import scala.language.postfixOps -import org.junit.runner.RunWith -import org.scalatest.junit.JUnitRunner -import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ +import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.server.Route +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner import spray.json.DefaultJsonProtocol._ import spray.json._ -import whisk.core.entity._ import whisk.core.controller.WhiskPackagesApi import whisk.core.entitlement.Collection -import whisk.http.ErrorResponse -import whisk.http.Messages +import whisk.core.entity._ +import whisk.http.{ErrorResponse, Messages} + +import scala.language.postfixOps /** * Tests Packages API. @@ -750,7 +750,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi { status should be(Conflict) val response = responseAs[ErrorResponse] response.error should include("Package not empty (contains 1 entity)") - response.code.id should be >= 1L + response.code.id should not be empty } } diff --git a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala index 97d5999..0dd5848 100644 --- a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala @@ -334,7 +334,7 @@ trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEac error.fields.get("error").get shouldBe JsString(m) } error.fields.get("code") shouldBe defined - error.fields.get("code").get shouldBe an[JsNumber] + error.fields.get("code").get shouldBe an[JsString] } Seq(None, Some(WhiskAuthHelpers.newIdentity())).foreach { creds => diff --git a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala index 7cf9074..b341bae 100644 --- a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala +++ b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala @@ -18,6 +18,7 @@ package whisk.core.database.test import java.util.concurrent.TimeoutException +import java.util.concurrent.atomic.AtomicInteger import scala.collection.mutable.ListBuffer import scala.concurrent.Await @@ -31,7 +32,6 @@ import scala.util.Success import scala.util.Try import spray.json._ import spray.json.DefaultJsonProtocol._ -import whisk.common.TransactionCounter import whisk.common.TransactionId import whisk.core.database._ import whisk.core.database.memory.MemoryArtifactStore @@ -45,13 +45,15 @@ import whisk.core.entity.types.EntityStore * operations with those that flow through the cache. To mitigate this, use unique asset * names in tests, and defer all cleanup to the end of a test suite. */ -trait DbUtils extends TransactionCounter { +trait DbUtils { implicit val dbOpTimeout = 15 seconds - override val instanceOrdinal = 0 - val instance = InstanceId(instanceOrdinal) + val instance = InstanceId(0) val docsToDelete = ListBuffer[(ArtifactStore[_], DocInfo)]() case class RetryOp() extends Throwable + val cnt = new AtomicInteger(0) + def transid() = TransactionId(cnt.incrementAndGet().toString) + /** * Retry an operation 'step()' awaiting its result up to 'timeout'. * Attempt the operation up to 'count' times. The future from the diff --git a/tests/src/test/scala/whisk/core/database/test/DocumentHandlerTests.scala b/tests/src/test/scala/whisk/core/database/test/DocumentHandlerTests.scala index c68fffd..20dc280 100644 --- a/tests/src/test/scala/whisk/core/database/test/DocumentHandlerTests.scala +++ b/tests/src/test/scala/whisk/core/database/test/DocumentHandlerTests.scala @@ -17,14 +17,16 @@ package whisk.core.database.test +import java.util.concurrent.atomic.AtomicInteger + +import common.WskActorSystem import org.junit.runner.RunWith -import org.scalatest.{FlatSpec, Matchers, OptionValues} +import org.scalatest.concurrent.ScalaFutures import org.scalatest.junit.JUnitRunner +import org.scalatest.{FlatSpec, Matchers, OptionValues} +import spray.json.DefaultJsonProtocol._ import spray.json._ -import DefaultJsonProtocol._ -import common.WskActorSystem -import org.scalatest.concurrent.ScalaFutures -import whisk.common.{TransactionCounter, TransactionId} +import whisk.common.TransactionId import whisk.core.database.SubjectHandler.SubjectView import whisk.core.database.WhisksHandler.ROOT_NS import whisk.core.database._ @@ -33,14 +35,10 @@ import whisk.core.entity._ import scala.concurrent.Future @RunWith(classOf[JUnitRunner]) -class DocumentHandlerTests - extends FlatSpec - with Matchers - with ScalaFutures - with OptionValues - with TransactionCounter - with WskActorSystem { - override val instanceOrdinal = 0 +class DocumentHandlerTests extends FlatSpec with Matchers with ScalaFutures with OptionValues with WskActorSystem { + + val cnt = new AtomicInteger(0) + def transid() = TransactionId(cnt.incrementAndGet().toString) behavior of "WhisksHandler computeFields" diff --git a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala index e13e420..e22063d 100644 --- a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala +++ b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala @@ -24,7 +24,7 @@ import common.{StreamLogging, WskActorSystem} import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures} import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FlatSpec, Matchers} import spray.json.{JsObject, JsValue} -import whisk.common.{TransactionCounter, TransactionId} +import whisk.common.TransactionId import whisk.core.database.test.DbUtils import whisk.core.database.{ArtifactStore, StaleParameter} import whisk.core.entity._ @@ -35,7 +35,6 @@ import scala.util.Random trait ArtifactStoreBehaviorBase extends FlatSpec with ScalaFutures - with TransactionCounter with Matchers with StreamLogging with DbUtils @@ -44,8 +43,6 @@ trait ArtifactStoreBehaviorBase with BeforeAndAfterEach with BeforeAndAfterAll { - override val instanceOrdinal = 0 - //Bring in sync the timeout used by ScalaFutures and DBUtils implicit override val patienceConfig: PatienceConfig = PatienceConfig(timeout = dbOpTimeout) diff --git a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala index d6111d0..99fe131 100644 --- a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala +++ b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala @@ -72,12 +72,12 @@ class SchemaTests extends FlatSpec with BeforeAndAfter with ExecHelpers with Mat behavior of "TransactionId" it should "serdes a transaction id without extraLogging parameter" in { - val txIdWithoutParameter = TransactionId(4711) + val txIdWithoutParameter = TransactionId("4711") // test serialization val serializedTxIdWithoutParameter = TransactionId.serdes.write(txIdWithoutParameter) serializedTxIdWithoutParameter match { - case JsArray(Vector(JsNumber(id), JsNumber(_))) => + case JsArray(Vector(JsString(id), JsNumber(_))) => assert(id == txIdWithoutParameter.meta.id) case _ => withClue(serializedTxIdWithoutParameter) { assert(false) } } @@ -89,12 +89,12 @@ class SchemaTests extends FlatSpec with BeforeAndAfter with ExecHelpers with Mat } it should "serdes a transaction id with extraLogging parameter" in { - val txIdWithParameter = TransactionId(4711, true) + val txIdWithParameter = TransactionId("4711", true) // test serialization val serializedTxIdWithParameter = TransactionId.serdes.write(txIdWithParameter) serializedTxIdWithParameter match { - case JsArray(Vector(JsNumber(id), JsNumber(_), JsBoolean(extraLogging))) => + case JsArray(Vector(JsString(id), JsNumber(_), JsBoolean(extraLogging))) => assert(id == txIdWithParameter.meta.id) assert(extraLogging) case _ => withClue(serializedTxIdWithParameter) { assert(false) } -- To stop receiving notification emails like this one, please contact markusthoem...@apache.org.