This is an automated email from the ASF dual-hosted git repository.

cbickel 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 b605943  Cleanup view for entities and augment activations view. 
(#2760)
b605943 is described below

commit b605943856d82b4253fa4539137e4e106d2fb07b
Author: rodric rabbah <rod...@gmail.com>
AuthorDate: Thu Nov 9 06:45:40 2017 -0500

    Cleanup view for entities and augment activations view. (#2760)
    
    - Factor out design doc name to ansible.
    - Separate index view into its own design doc. This will cut the main view 
file size in half which will make activation list faster. It replicates the 
view in a separate design doc, so the total savings are zero. The additional 
compute overhead for the ddoc though is worth considering. The upshot: we can 
adjust filters separately.
    - Add package prefix if it exists to activation filter.
    - Allow for filtering activations by package name.
---
 ...ign_document_for_activations_db_filters_v2.json |  9 ++
 ...isks_design_document_for_activations_db_v2.json |  9 ++
 .../whisks_design_document_for_entities_db_v2.json | 21 +++++
 ansible/group_vars/all                             |  3 +
 ansible/roles/controller/tasks/deploy.yml          |  5 +-
 ansible/roles/invoker/tasks/deploy.yml             |  3 +
 ansible/tasks/recreateViews.yml                    |  3 +
 ansible/templates/whisk.properties.j2              |  5 +-
 .../src/main/scala/whisk/core/WhiskConfig.scala    | 25 ++++--
 .../main/scala/whisk/core/entity/EntityPath.scala  |  5 ++
 .../scala/whisk/core/entity/WhiskActivation.scala  | 60 ++++++++++---
 .../main/scala/whisk/core/entity/WhiskStore.scala  | 51 +++++++++---
 .../src/main/scala/whisk/http/ErrorResponse.scala  |  3 +-
 .../scala/whisk/core/controller/Activations.scala  | 55 ++++++------
 .../main/scala/whisk/core/invoker/Invoker.scala    | 15 +++-
 .../core/controller/test/ActivationsApiTests.scala | 59 +++++++++++--
 .../scala/whisk/core/database/test/DbUtils.scala   | 11 ++-
 .../scala/whisk/core/entity/test/ViewTests.scala   | 97 +++++++++-------------
 18 files changed, 297 insertions(+), 142 deletions(-)

diff --git 
a/ansible/files/whisks_design_document_for_activations_db_filters_v2.json 
b/ansible/files/whisks_design_document_for_activations_db_filters_v2.json
new file mode 100644
index 0000000..14eb0b0
--- /dev/null
+++ b/ansible/files/whisks_design_document_for_activations_db_filters_v2.json
@@ -0,0 +1,9 @@
+{
+  "_id": "_design/whisks-filters.v2",
+  "language": "javascript",
+  "views": {
+    "activations": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n  var isActivation = 
function (doc) { return (doc.activationId !== undefined) };\n  var summarize = 
function (doc) {\n    var endtime = doc.end !== 0 ? doc.end : undefined;\n    
return {\n        namespace: doc.namespace,\n        name: doc.name,\n        
version: doc.version,\n        publish: doc.publish,\n        annotations: 
doc.annotations,\n        activationId: doc.activationId,\n        start: 
doc.start,\n        end: endtim [...]
+    }
+  }
+}
diff --git a/ansible/files/whisks_design_document_for_activations_db_v2.json 
b/ansible/files/whisks_design_document_for_activations_db_v2.json
new file mode 100644
index 0000000..be57879
--- /dev/null
+++ b/ansible/files/whisks_design_document_for_activations_db_v2.json
@@ -0,0 +1,9 @@
+{
+  "_id": "_design/whisks.v2",
+  "language": "javascript",
+  "views": {
+    "activations": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n  var isActivation = 
function (doc) { return (doc.activationId !== undefined) };\n  var summarize = 
function (doc) {\n    var endtime = doc.end !== 0 ? doc.end : undefined;\n    
return {\n        namespace: doc.namespace,\n        name: doc.name,\n        
version: doc.version,\n        publish: doc.publish,\n        annotations: 
doc.annotations,\n        activationId: doc.activationId,\n        start: 
doc.start,\n        end: endtim [...]
+    }
+  }
+}
diff --git a/ansible/files/whisks_design_document_for_entities_db_v2.json 
b/ansible/files/whisks_design_document_for_entities_db_v2.json
new file mode 100644
index 0000000..97ed91c
--- /dev/null
+++ b/ansible/files/whisks_design_document_for_entities_db_v2.json
@@ -0,0 +1,21 @@
+{
+  "_id": "_design/whisks.v2",
+  "language": "javascript",
+  "views": {
+    "rules": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n  var isRule = 
function (doc) {  return (doc.trigger !== undefined) };\n  if (isRule(doc)) try 
{\n    var ns = doc.namespace.split(PATHSEP);\n    var root = ns[0];\n    var 
date = doc.updated;\n    var value = {\n      namespace: doc.namespace,\n      
name: doc.name,\n      version: doc.version,\n      publish: doc.publish,\n     
 annotations: doc.annotations\n    };\n    emit([doc.namespace, date], 
value);\n    if (root !== doc.nam [...]
+    },
+    "all": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n\n  var isPackage = 
function (doc) {  return (doc.binding !== undefined) };\n  var isAction = 
function (doc) { return (doc.exec !== undefined) };\n  var isTrigger = function 
(doc) { return (doc.exec === undefined && doc.binding === undefined && 
doc.parameters !== undefined) };\n  var isRule = function (doc) {  return 
(doc.trigger !== undefined) };\n  \n  var collection = function (doc) {\n    if 
(isPackage(doc)) return \"packages\"; [...]
+    },
+    "packages": {
+      "map": "function (doc) {\n  var isPackage = function (doc) {  return 
(doc.binding !== undefined) };\n  if (isPackage(doc)) try {\n    var date = 
doc.updated;\n    emit([doc.namespace, date], {\n      namespace: 
doc.namespace,\n      name: doc.name,\n      version: doc.version,\n      
publish: doc.publish,\n      annotations: doc.annotations,\n      binding: 
Object.keys(doc.binding).length !== 0\n    });\n  } catch (e) {}\n}"
+    },
+    "actions": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n  var isAction = 
function (doc) { return (doc.exec !== undefined) };\n  if (isAction(doc)) try 
{\n    var ns = doc.namespace.split(PATHSEP);\n    var root = ns[0];\n    var 
date = doc.updated;\n    var value = {\n      namespace: doc.namespace,\n      
name: doc.name,\n      version: doc.version,\n      publish: doc.publish,\n     
 annotations: doc.annotations\n    };\n    emit([doc.namespace, date], 
value);\n    if (root !== doc.nam [...]
+    },
+    "triggers": {
+      "map": "function (doc) {\n  var PATHSEP = \"/\";\n  var isTrigger = 
function (doc) { return (doc.exec === undefined && doc.binding === undefined && 
doc.parameters !== undefined) };\n  if (isTrigger(doc)) try {\n    var ns = 
doc.namespace.split(PATHSEP);\n    var root = ns[0];\n    var date = 
doc.updated;\n    var value = {\n      namespace: doc.namespace,\n      name: 
doc.name,\n      version: doc.version,\n      publish: doc.publish,\n      
annotations: doc.annotations\n    };\n   [...]
+    }
+  }
+}
\ No newline at end of file
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
index d7dfae9..79642fe 100644
--- a/ansible/group_vars/all
+++ b/ansible/group_vars/all
@@ -198,7 +198,10 @@ db:
   - whisk.system
   whisk:
     actions: "{{ db_prefix }}whisks"
+    actions_ddoc: "whisks"
     activations: "{{ db_prefix }}activations"
+    activations_ddoc: "whisks"
+    activations_filter_ddoc: "whisks"
     auth: "{{ db_prefix }}subjects"
 
 apigateway:
diff --git a/ansible/roles/controller/tasks/deploy.yml 
b/ansible/roles/controller/tasks/deploy.yml
index d128053..c669395 100644
--- a/ansible/roles/controller/tasks/deploy.yml
+++ b/ansible/roles/controller/tasks/deploy.yml
@@ -60,9 +60,12 @@
       "DB_PORT": "{{ db_port }}"
       "DB_USERNAME": "{{ db_username }}"
       "DB_PASSWORD": "{{ db_password }}"
-      "DB_WHISK_ACTIONS": "{{ db.whisk.actions }}"
       "DB_WHISK_AUTHS": "{{ db.whisk.auth }}"
+      "DB_WHISK_ACTIONS": "{{ db.whisk.actions }}"
       "DB_WHISK_ACTIVATIONS": "{{ db.whisk.activations }}"
+      "DB_WHISK_ACTIONS_DDOC": "{{ db.whisk.actions_ddoc }}"
+      "DB_WHISK_ACTIVATIONS_DDOC": "{{ db.whisk.activations_ddoc }}"
+      "DB_WHISK_ACTIVATIONS_FILTER_DDOC": "{{ db.whisk.activations_filter_ddoc 
}}"
 
       "LIMITS_ACTIONS_INVOKES_PERMINUTE": "{{ limits.invocationsPerMinute }}"
       "LIMITS_ACTIONS_INVOKES_CONCURRENT": "{{ limits.concurrentInvocations }}"
diff --git a/ansible/roles/invoker/tasks/deploy.yml 
b/ansible/roles/invoker/tasks/deploy.yml
index 2b8dc7c..b7d9fc2 100644
--- a/ansible/roles/invoker/tasks/deploy.yml
+++ b/ansible/roles/invoker/tasks/deploy.yml
@@ -129,6 +129,9 @@
         -e DB_PASSWORD='{{ db_password }}'
         -e DB_WHISK_ACTIONS='{{ db.whisk.actions }}'
         -e DB_WHISK_ACTIVATIONS='{{ db.whisk.activations }}'
+        -e DB_WHISK_ACTIONS_DDOC='{{ db.whisk.actions_ddoc }}'
+        -e DB_WHISK_ACTIVATIONS_DDOC='{{ db.whisk.activations_ddoc }}'
+        -e DB_WHISK_ACTIVATIONS_FILTER_DDOC='{{ 
db.whisk.activations_filter_ddoc }}'
         -e WHISK_API_HOST_PROTO='{{ whisk_api_host_proto | default('https') }}'
         -e WHISK_API_HOST_PORT='{{ whisk_api_host_port | default('443') }}'
         -e WHISK_API_HOST_NAME='{{ whisk_api_host_name | 
default(groups['edge'] | first) }}'
diff --git a/ansible/tasks/recreateViews.yml b/ansible/tasks/recreateViews.yml
index e953320..682ca94 100644
--- a/ansible/tasks/recreateViews.yml
+++ b/ansible/tasks/recreateViews.yml
@@ -7,6 +7,7 @@
     doc: "{{ lookup('file', '{{ item }}') }}"
   with_items:
     - "{{ openwhisk_home 
}}/ansible/files/whisks_design_document_for_actions_db.json"
+    - "{{ openwhisk_home 
}}/ansible/files/whisks_design_document_for_entities_db_v2.json"
     - "{{ openwhisk_home }}/ansible/files/filter_design_document.json"
 
 - include: db/recreateDoc.yml
@@ -15,6 +16,8 @@
     doc: "{{ lookup('file', '{{ item }}') }}"
   with_items:
     - "{{ openwhisk_home 
}}/ansible/files/whisks_design_document_for_activations_db.json"
+    - "{{ openwhisk_home 
}}/ansible/files/whisks_design_document_for_activations_db_v2.json"
+    - "{{ openwhisk_home 
}}/ansible/files/whisks_design_document_for_activations_db_filters_v2.json"
     - "{{ openwhisk_home }}/ansible/files/filter_design_document.json"
     - "{{ openwhisk_home 
}}/ansible/files/activations_design_document_for_activations_db.json"
     - "{{ openwhisk_home 
}}/ansible/files/logCleanup_design_document_for_activations_db.json"
diff --git a/ansible/templates/whisk.properties.j2 
b/ansible/templates/whisk.properties.j2
index e23e624..2c1d644 100644
--- a/ansible/templates/whisk.properties.j2
+++ b/ansible/templates/whisk.properties.j2
@@ -87,9 +87,12 @@ db.port={{ db_port }}
 db.username={{ db_username }}
 db.password={{ db_password }}
 db.prefix={{ db_prefix }}
+db.whisk.auths={{ db.whisk.auth }}
 db.whisk.actions={{ db.whisk.actions }}
 db.whisk.activations={{ db.whisk.activations }}
-db.whisk.auths={{ db.whisk.auth }}
+db.whisk.actions.ddoc={{ db.whisk.actions_ddoc }}
+db.whisk.activations.ddoc={{ db.whisk.activations_ddoc }}
+db.whisk.activations.filter.ddoc={{ db.whisk.activations_filter_ddoc }}
 
 apigw.auth.user={{apigw_auth_user}}
 apigw.auth.pwd={{apigw_auth_pwd}}
diff --git a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala 
b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
index 56da847..726d1bc 100644
--- a/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
+++ b/common/scala/src/main/scala/whisk/core/WhiskConfig.scala
@@ -30,12 +30,13 @@ import whisk.common.{Config, Logging}
  * a value, and whose values are default values. A null value in the Map means 
there is
  * no default value specified, so it must appear in the properties file.
  * @param optionalProperties a set of optional properties (which may not be 
defined).
- * @param whiskPropertiesFile a File object, the whisk.properties file, which 
if given contains the property values.
+ * @param propertiesFile a File object, the whisk.properties file, which if 
given contains the property values.
+ * @param env an optional environment to initialize from.
  */
 class WhiskConfig(requiredProperties: Map[String, String],
                   optionalProperties: Set[String] = Set(),
                   propertiesFile: File = null,
-                  env: Map[String, String] = sys.env)(implicit val logging: 
Logging)
+                  env: Map[String, String] = sys.env)(implicit logging: 
Logging)
     extends Config(requiredProperties, optionalProperties)(env) {
 
   /**
@@ -89,10 +90,10 @@ class WhiskConfig(requiredProperties: Map[String, String],
   val dbProtocol = this(WhiskConfig.dbProtocol)
   val dbHost = this(WhiskConfig.dbHost)
   val dbPort = this(WhiskConfig.dbPort)
-  val dbWhisk = this(WhiskConfig.dbWhisk)
+  val dbPrefix = this(WhiskConfig.dbPrefix)
   val dbAuths = this(WhiskConfig.dbAuths)
+  val dbWhisk = this(WhiskConfig.dbWhisk)
   val dbActivations = this(WhiskConfig.dbActivations)
-  val dbPrefix = this(WhiskConfig.dbPrefix)
 
   val mainDockerEndpoint = this(WhiskConfig.mainDockerEndpoint)
 
@@ -104,11 +105,15 @@ class WhiskConfig(requiredProperties: Map[String, String],
   val actionSequenceLimit = this(WhiskConfig.actionSequenceMaxLimit)
   val controllerSeedNodes = this(WhiskConfig.controllerSeedNodes)
   val controllerLocalBookkeeping = 
getAsBoolean(WhiskConfig.controllerLocalBookkeeping, false)
-
 }
 
 object WhiskConfig {
 
+  /**
+   * Reads a key from system environment as if it was part of WhiskConfig.
+   */
+  def readFromEnv(key: String): Option[String] = sys.env.get(asEnvVar(key))
+
   private def whiskPropertiesFile: File = {
     def propfile(dir: String, recurse: Boolean = false): File =
       if (dir != null) {
@@ -153,10 +158,11 @@ object WhiskConfig {
     }
   }
 
-  def asEnvVar(key: String): String =
+  def asEnvVar(key: String): String = {
     if (key != null)
       key.replace('.', '_').toUpperCase
     else null
+  }
 
   val servicePort = "port"
   val dockerRegistry = "docker.registry"
@@ -170,10 +176,13 @@ object WhiskConfig {
   val dbPort = "db.port"
   val dbUsername = "db.username"
   val dbPassword = "db.password"
-  val dbWhisk = "db.whisk.actions"
-  val dbAuths = "db.whisk.auths"
   val dbPrefix = "db.prefix"
+  val dbAuths = "db.whisk.auths"
+  val dbWhisk = "db.whisk.actions"
   val dbActivations = "db.whisk.activations"
+  val dbWhiskDesignDoc = "db.whisk.actions.ddoc"
+  val dbActivationsDesignDoc = "db.whisk.activations.ddoc"
+  val dbActivationsFilterDesignDoc = "db.whisk.activations.filter.ddoc"
 
   // these are not private because they are needed
   // in the invoker (they are part of the environment
diff --git a/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala 
b/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala
index 26e1fb1..c4836c3 100644
--- a/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala
@@ -43,6 +43,11 @@ protected[core] class EntityPath private (private val path: 
Seq[String]) extends
   def namespace: String = path.foldLeft("")((a, b) => if (a != "") a.trim + 
EntityPath.PATHSEP + b.trim else b.trim)
 
   /**
+   * @return number of parts in the path.
+   */
+  def segments = path.length
+
+  /**
    * Adds segment to path.
    */
   def addPath(e: EntityName) = EntityPath(path :+ e.name)
diff --git 
a/common/scala/src/main/scala/whisk/core/entity/WhiskActivation.scala 
b/common/scala/src/main/scala/whisk/core/entity/WhiskActivation.scala
index 3dca9c1..4073093 100644
--- a/common/scala/src/main/scala/whisk/core/entity/WhiskActivation.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/WhiskActivation.scala
@@ -23,12 +23,13 @@ import scala.concurrent.Future
 import scala.util.Try
 
 import spray.json._
-import spray.json.DefaultJsonProtocol
 import spray.json.DefaultJsonProtocol._
 import whisk.common.TransactionId
 import whisk.core.database.ArtifactStore
 import whisk.core.database.DocumentFactory
 import whisk.core.database.StaleParameter
+import whisk.core.WhiskConfig
+import whisk.core.WhiskConfig.{dbActivationsDesignDoc, 
dbActivationsFilterDesignDoc}
 
 /**
  * A WhiskActivation provides an abstraction of the meta-data
@@ -77,8 +78,25 @@ case class WhiskActivation(namespace: EntityPath,
 
   /** This the activation summary as computed by the database view. Strictly 
used for testing. */
   override def summaryAsJson = {
-    val JsObject(fields) = super.summaryAsJson
-    JsObject(fields + ("activationId" -> activationId.toJson))
+    import WhiskActivation.instantSerdes
+    val summary = JsObject(super.summaryAsJson.fields + ("activationId" -> 
activationId.toJson))
+
+    def actionOrNot() = {
+      if (end != Instant.EPOCH) {
+        Map(
+          "end" -> end.toJson,
+          "duration" -> (duration getOrElse (end.toEpochMilli - 
start.toEpochMilli)).toJson,
+          "statusCode" -> response.statusCode.toJson)
+      } else Map.empty
+    }
+
+    if (WhiskActivation.mainDdoc.endsWith(".v2")) {
+      JsObject(
+        summary.fields +
+          ("start" -> start.toJson) ++
+          cause.map(("cause" -> _.toJson)) ++
+          actionOrNot())
+    } else summary
   }
 
   def resultAsJson = response.result.toJson.asJsObject
@@ -94,8 +112,10 @@ case class WhiskActivation(namespace: EntityPath,
     }
   }
 
-  def withoutLogsOrResult =
+  def withoutLogsOrResult = {
     copy(response = response.withoutResult, logs = 
ActivationLogs()).revision[WhiskActivation](rev)
+  }
+
   def withoutLogs = copy(logs = 
ActivationLogs()).revision[WhiskActivation](rev)
   def withLogs(logs: ActivationLogs) = copy(logs = 
logs).revision[WhiskActivation](rev)
 }
@@ -119,6 +139,24 @@ object WhiskActivation
   }
 
   override val collectionName = "activations"
+
+  // FIXME: reading the design doc from sys.env instead of a canonical 
property reader
+  // because WhiskConfig requires a logger, which requires an actor system, 
neither of
+  // which are readily available here; rather than introduce significant 
refactoring,
+  // defer this fix until WhiskConfig is refactored itself, which is planned 
to introduce
+  // type safe properties
+  private val mainDdoc = 
WhiskConfig.readFromEnv(dbActivationsDesignDoc).getOrElse("whisks")
+  private val filtersDdoc = 
WhiskConfig.readFromEnv(dbActivationsFilterDesignDoc).getOrElse("whisks")
+
+  /** The main view for activations, keyed by namespace, sorted by date. */
+  override lazy val view = WhiskEntityQueries.view(mainDdoc, collectionName)
+
+  /**
+   * A view for activations in a namespace additionally keyed by action name
+   * (and package name if present) sorted by date.
+   */
+  private val filtersView = WhiskEntityQueries.view(filtersDdoc, 
collectionName)
+
   override implicit val serdes = jsonFormat13(WhiskActivation.apply)
 
   // Caching activations doesn't make much sense in the common case as usually,
@@ -134,18 +172,18 @@ object WhiskActivation
    */
   def listActivationsMatchingName(db: ArtifactStore[WhiskActivation],
                                   namespace: EntityPath,
-                                  name: EntityName,
+                                  path: EntityPath,
                                   skip: Int,
                                   limit: Int,
-                                  docs: Boolean = false,
+                                  includeDocs: Boolean = false,
                                   since: Option[Instant] = None,
                                   upto: Option[Instant] = None,
                                   stale: StaleParameter = StaleParameter.No)(
     implicit transid: TransactionId): Future[Either[List[JsObject], 
List[WhiskActivation]]] = {
-    import WhiskEntityQueries._
-    val convert = if (docs) Some((o: JsObject) => Try { serdes.read(o) }) else 
None
-    val startKey = List(namespace.addPath(name).asString, since map { 
_.toEpochMilli } getOrElse 0)
-    val endKey = List(namespace.addPath(name).asString, upto map { 
_.toEpochMilli } getOrElse TOP, TOP)
-    query(db, viewname(collectionName), startKey, endKey, skip, limit, reduce 
= false, stale, convert)
+    import WhiskEntityQueries.TOP
+    val convert = if (includeDocs) Some((o: JsObject) => Try { serdes.read(o) 
}) else None
+    val startKey = List(namespace.addPath(path).asString, since map { 
_.toEpochMilli } getOrElse 0)
+    val endKey = List(namespace.addPath(path).asString, upto map { 
_.toEpochMilli } getOrElse TOP, TOP)
+    query(db, filtersView, startKey, endKey, skip, limit, reduce = false, 
stale, convert)
   }
 }
diff --git a/common/scala/src/main/scala/whisk/core/entity/WhiskStore.scala 
b/common/scala/src/main/scala/whisk/core/entity/WhiskStore.scala
index df8d1fe..28addc2 100644
--- a/common/scala/src/main/scala/whisk/core/entity/WhiskStore.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/WhiskStore.scala
@@ -22,7 +22,6 @@ import java.time.Instant
 import scala.concurrent.Future
 import scala.language.postfixOps
 import scala.util.Try
-
 import akka.actor.ActorSystem
 import akka.stream.ActorMaterializer
 import spray.json.JsObject
@@ -40,6 +39,8 @@ import whisk.core.WhiskConfig.dbProtocol
 import whisk.core.WhiskConfig.dbProvider
 import whisk.core.WhiskConfig.dbUsername
 import whisk.core.WhiskConfig.dbWhisk
+import whisk.core.WhiskConfig.dbWhiskDesignDoc
+import whisk.core.WhiskConfig.dbActivationsDesignDoc
 import whisk.core.database.ArtifactStore
 import whisk.core.database.ArtifactStoreProvider
 import whisk.core.database.DocumentRevisionProvider
@@ -111,7 +112,8 @@ object WhiskEntityStore {
       dbPassword -> null,
       dbHost -> null,
       dbPort -> null,
-      dbWhisk -> null)
+      dbWhisk -> null,
+      dbWhiskDesignDoc -> null)
 
   def datastore(config: WhiskConfig)(implicit system: ActorSystem, logging: 
Logging, materializer: ActorMaterializer) =
     SpiLoader
@@ -129,13 +131,26 @@ object WhiskActivationStore {
       dbPassword -> null,
       dbHost -> null,
       dbPort -> null,
-      dbActivations -> null)
+      dbActivations -> null,
+      dbActivationsDesignDoc -> null)
 
   def datastore(config: WhiskConfig)(implicit system: ActorSystem, logging: 
Logging, materializer: ActorMaterializer) =
     SpiLoader.get[ArtifactStoreProvider].makeStore[WhiskActivation](config, 
_.dbActivations, true)
 }
 
 /**
+ * A class to type the design doc and view within a database.
+ *
+ * @param ddoc the design document
+ * @param view the view name within the design doc
+ */
+protected[core] class View(ddoc: String, view: String) {
+
+  /** The name of the table to query. */
+  val name = s"$ddoc/$view"
+}
+
+/**
  * This object provides some utilities that query the whisk datastore.
  * The datastore is assumed to have views (pre-computed joins or indexes)
  * for each of the whisk collection types. Entities may be queries by
@@ -169,14 +184,23 @@ object WhiskActivationStore {
  */
 object WhiskEntityQueries {
   val TOP = "\ufff0"
-  val WHISKVIEW = "whisks"
-  val ALL = "all"
+
+  /** The design document to use for queries. */
+  // FIXME: reading the design doc from sys.env instead of a canonical 
property reader
+  // because WhiskConfig requires a logger, which requires an actor system, 
neither of
+  // which are readily available here; rather than introduce significant 
refactoring,
+  // defer this fix until WhiskConfig is refactored itself, which is planned 
to introduce
+  // type safe properties
+  val designDoc = WhiskConfig.readFromEnv(dbWhiskDesignDoc).getOrElse("whisks")
+
+  /** The view name for the collection, within the design document. */
+  def view(ddoc: String = designDoc, collection: String) = new View(ddoc, 
collection)
 
   /**
-   * Determines the view name for the collection. There are two cases: a view
-   * that is namespace specific, or namespace agnostic..
+   * Name of view in design-doc that lists all entities in that views 
regardless of types.
+   * This is uses in the namespace API, and also in tests to check 
preconditions.
    */
-  def viewname(collection: String): String = s"$WHISKVIEW/$collection"
+  val viewAll: View = view(collection = "all")
 
   /**
    * Queries the datastore for all entities in a namespace, and converts the 
list of entities
@@ -191,7 +215,7 @@ object WhiskEntityQueries {
     implicit val ec = db.executionContext
     val startKey = List(namespace.asString)
     val endKey = List(namespace.asString, TOP)
-    db.query(viewname(ALL), startKey, endKey, 0, 0, includeDocs, descending = 
true, reduce = false, stale = stale) map {
+    db.query(viewAll.name, startKey, endKey, 0, 0, includeDocs, descending = 
true, reduce = false, stale = stale) map {
       _ map { row =>
         val value = row.fields("value").asJsObject
         val JsString(collection) = value.fields("collection")
@@ -206,6 +230,9 @@ trait WhiskEntityQueries[T] {
   val serdes: RootJsonFormat[T]
   import WhiskEntityQueries._
 
+  /** The view name for the collection, within the design document. */
+  lazy val view: View = WhiskEntityQueries.view(collection = collectionName)
+
   /**
    * Queries the datastore for records from a specific collection (i.e., type) 
matching
    * the given path (which should be one namespace, or namespace + package 
name).
@@ -225,12 +252,12 @@ trait WhiskEntityQueries[T] {
     val convert = if (includeDocs) Some((o: JsObject) => Try { serdes.read(o) 
}) else None
     val startKey = List(path.asString, since map { _.toEpochMilli } getOrElse 
0)
     val endKey = List(path.asString, upto map { _.toEpochMilli } getOrElse 
TOP, TOP)
-    query(db, viewname(collectionName), startKey, endKey, skip, limit, reduce 
= false, stale, convert)
+    query(db, view, startKey, endKey, skip, limit, reduce = false, stale, 
convert)
   }
 
   protected[entity] def query[A <: WhiskEntity](
     db: ArtifactStore[A],
-    view: String,
+    view: View,
     startKey: List[Any],
     endKey: List[Any],
     skip: Int,
@@ -240,7 +267,7 @@ trait WhiskEntityQueries[T] {
     convert: Option[JsObject => Try[T]])(implicit transid: TransactionId): 
Future[Either[List[JsObject], List[T]]] = {
     implicit val ec = db.executionContext
     val includeDocs = convert.isDefined
-    db.query(view, startKey, endKey, skip, limit, includeDocs, true, reduce, 
stale) map { rows =>
+    db.query(view.name, startKey, endKey, skip, limit, includeDocs, true, 
reduce, stale) map { rows =>
       convert map { fn =>
         Right(rows flatMap { row =>
           fn(row.fields("doc").asJsObject) toOption
diff --git a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala 
b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
index 09c3bfe..719a6c5 100644
--- a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
+++ b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
@@ -113,8 +113,7 @@ object Messages {
   val abnormalInitialization = "The action did not initialize and exited 
unexpectedly."
   val abnormalRun = "The action did not produce a valid response and exited 
unexpectedly."
   val memoryExhausted = "The action exhausted its memory and was aborted."
-  def badEntityName(value: String) = s"Parameter is not a valid value for a 
entity name: $value"
-  def badNamespace(value: String) = s"Parameter is not a valid value for a 
namespace: $value"
+  def badNameFilter(value: String) = s"Parameter may be a 'simple' name or 
'package-name/simple' name: $value"
   def badEpoch(value: String) = s"Parameter is not a valid value for epoch 
seconds: $value"
 
   /** Error message for size conformance. */
diff --git 
a/core/controller/src/main/scala/whisk/core/controller/Activations.scala 
b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
index 0d7dbbc..0403d1c 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Activations.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
@@ -43,6 +43,25 @@ import whisk.http.Messages
 
 object WhiskActivationsApi {
   protected[core] val maxActivationLimit = 200
+
+  /** Custom unmarshaller for query parameters "name" into valid 
package/action name path. */
+  private implicit val stringToRestrictedEntityPath: Unmarshaller[String, 
Option[EntityPath]] =
+    Unmarshaller.strict[String, Option[EntityPath]] { value =>
+      Try { EntityPath(value) } match {
+        case Success(e) if e.segments <= 2 => Some(e)
+        case _ if value.trim.isEmpty       => None
+        case _                             => throw new 
IllegalArgumentException(Messages.badNameFilter(value))
+      }
+    }
+
+  /** Custom unmarshaller for query parameters "since" and "upto" into a valid 
Instant. */
+  private implicit val stringToInstantDeserializer: Unmarshaller[String, 
Instant] =
+    Unmarshaller.strict[String, Instant] { value =>
+      Try { Instant.ofEpochMilli(value.toLong) } match {
+        case Success(e) => e
+        case Failure(t) => throw new 
IllegalArgumentException(Messages.badEpoch(value))
+      }
+    }
 }
 
 /** A trait implementing the activations API. */
@@ -118,24 +137,27 @@ trait WhiskActivationsApi extends Directives with 
AuthenticatedRouteProvider wit
    * - 500 Internal Server Error
    */
   private def list(namespace: EntityPath)(implicit transid: TransactionId) = {
+    import WhiskActivationsApi.stringToRestrictedEntityPath
+    import WhiskActivationsApi.stringToInstantDeserializer
+
     parameter(
       'skip ? 0,
       'limit ? collection.listLimit,
       'count ? false,
       'docs ? false,
-      'name.as[EntityName] ?,
+      'name.as[Option[EntityPath]] ?,
       'since.as[Instant] ?,
       'upto.as[Instant] ?) { (skip, limit, count, docs, name, since, upto) =>
       val cappedLimit = if (limit == 0) WhiskActivationsApi.maxActivationLimit 
else limit
 
       // regardless of limit, cap at maxActivationLimit (200) records, client 
must paginate
       if (cappedLimit <= WhiskActivationsApi.maxActivationLimit) {
-        val activations = name match {
+        val activations = name.flatten match {
           case Some(action) =>
             WhiskActivation.listActivationsMatchingName(
               activationStore,
               namespace,
-              action,
+              action.last.toPath,
               skip,
               cappedLimit,
               docs,
@@ -215,31 +237,4 @@ trait WhiskActivationsApi extends Directives with 
AuthenticatedRouteProvider wit
       docid,
       (activation: WhiskActivation) => 
logStore.fetchLogs(activation).map(_.toJsonObject))
   }
-
-  /** Custom unmarshaller for query parameters "name" into valid entity name. 
*/
-  private implicit val stringToEntityName: Unmarshaller[String, EntityName] =
-    Unmarshaller.strict[String, EntityName] { value =>
-      Try { EntityName(value) } match {
-        case Success(e) => e
-        case Failure(t) => throw new 
IllegalArgumentException(Messages.badEntityName(value))
-      }
-    }
-
-  /** Custom unmarshaller for query parameters "name" into valid namespace. */
-  private implicit val stringToNamespace: Unmarshaller[String, EntityPath] =
-    Unmarshaller.strict[String, EntityPath] { value =>
-      Try { EntityPath(value) } match {
-        case Success(e) => e
-        case Failure(t) => throw new 
IllegalArgumentException(Messages.badNamespace(value))
-      }
-    }
-
-  /** Custom unmarshaller for query parameters "since" and "upto" into a valid 
Instant. */
-  private implicit val stringToInstantDeserializer: Unmarshaller[String, 
Instant] =
-    Unmarshaller.strict[String, Instant] { value =>
-      Try { Instant.ofEpochMilli(value.toLong) } match {
-        case Success(e) => e
-        case Failure(t) => throw new 
IllegalArgumentException(Messages.badEpoch(value))
-      }
-    }
 }
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 8c57206..192100d 100644
--- a/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala
+++ b/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala
@@ -137,19 +137,22 @@ object Invoker {
         if (invokerName.trim.isEmpty) {
           abort("Invoker name can't be empty to use dynamicId assignment.")
         }
+
         logger.info(this, s"invokerReg: creating zkClient to 
${config.zookeeperHost}")
         val retryPolicy = new RetryUntilElapsed(5000, 500) // retry at 500ms 
intervals until 5 seconds have elapsed
         val zkClient = CuratorFrameworkFactory.newClient(config.zookeeperHost, 
retryPolicy)
         zkClient.start()
-        zkClient.blockUntilConnected();
+        zkClient.blockUntilConnected()
         logger.info(this, "invokerReg: connected to zookeeper")
+
         val myIdPath = "/invokers/idAssignment/mapping/" + invokerName
         val assignedId = Option(zkClient.checkExists().forPath(myIdPath)) 
match {
           case None =>
-            // path doesn't exist ==> no previous mapping for this invoker
+            // path doesn't exist -> no previous mapping for this invoker
             logger.info(this, s"invokerReg: no prior assignment of id for 
invoker $invokerName")
             val idCounter = new SharedCount(zkClient, 
"/invokers/idAssignment/counter", 0)
             idCounter.start()
+
             def assignId(): Int = {
               val current = idCounter.getVersionedValue()
               if (idCounter.trySetCount(current, current.getValue() + 1)) {
@@ -158,22 +161,26 @@ object Invoker {
                 assignId()
               }
             }
+
             val newId = assignId()
             idCounter.close()
             
zkClient.create().creatingParentContainersIfNeeded().forPath(myIdPath, 
BigInt(newId).toByteArray)
             logger.info(this, s"invokerReg: invoker ${invokerName} was 
assigned invokerId ${newId}")
             newId
+
           case Some(_) =>
-            // path already exists ==> there is a previous mapping for this 
invoker we should use
+            // path already exists -> there is a previous mapping for this 
invoker we should use
             val rawOldId = zkClient.getData().forPath(myIdPath)
             val oldId = BigInt(rawOldId).intValue
             logger.info(this, s"invokerReg: invoker ${invokerName} was 
assigned its previous invokerId ${oldId}")
             oldId
         }
+
         zkClient.close()
         assignedId
       }
-    val invokerInstance = InstanceId(assignedInvokerId);
+
+    val invokerInstance = InstanceId(assignedInvokerId)
     val msgProvider = SpiLoader.get[MessagingProvider]
     val producer = msgProvider.getProducer(config, ec)
     val invoker = try {
diff --git 
a/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala 
b/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
index 548c612..9f99eda 100644
--- a/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
@@ -80,7 +80,7 @@ class ActivationsApiTests extends ControllerTestCommon with 
WhiskActivationsApi
       WhiskActivation(namespace, actionName, creds.subject, ActivationId(), 
start = Instant.now, end = Instant.now)
     }.toList
     activations foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace.root, 2, 
WhiskActivation.collectionName)
+    waitOnView(activationStore, namespace.root, 2, WhiskActivation.view)
     whisk.utils.retry {
       Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
         status should be(OK)
@@ -152,7 +152,7 @@ class ActivationsApiTests extends ControllerTestCommon with 
WhiskActivationsApi
         response = ActivationResponse.success(Some(JsNumber(5))))
     }.toList
     activations foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace.root, 2, 
WhiskActivation.collectionName)
+    waitOnView(activationStore, namespace.root, 2, WhiskActivation.view)
 
     whisk.utils.retry {
       Get(s"$collectionPath?docs=true") ~> Route.seal(routes(creds)) ~> check {
@@ -216,7 +216,7 @@ class ActivationsApiTests extends ControllerTestCommon with 
WhiskActivationsApi
         start = now.plusSeconds(30),
         end = now.plusSeconds(20))) // should match
     activations foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace.root, activations.length, 
WhiskActivation.collectionName)
+    waitOnView(activationStore, namespace.root, activations.length, 
WhiskActivation.view)
 
     // get between two time stamps
     whisk.utils.retry {
@@ -267,6 +267,20 @@ class ActivationsApiTests extends ControllerTestCommon 
with WhiskActivationsApi
   }
 
   //// GET /activations?name=xyz
+  it should "accept valid name parameters and reject invalid ones" in {
+    implicit val tid = transid()
+
+    Seq(("", OK), ("name=", OK), ("name=abc", OK), ("name=abc/xyz", OK), 
("name=abc/xyz/123", BadRequest)).foreach {
+      case (p, s) =>
+        Get(s"$collectionPath?$p") ~> Route.seal(routes(creds)) ~> check {
+          status should be(s)
+          if (s == BadRequest) {
+            responseAs[String] should 
include(Messages.badNameFilter(p.drop(5)))
+          }
+        }
+    }
+  }
+
   it should "get summary activation by namespace and action name" in {
     implicit val tid = transid()
 
@@ -292,18 +306,46 @@ class ActivationsApiTests extends ControllerTestCommon 
with WhiskActivationsApi
         end = Instant.now)
     }.toList
     activations foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace.root, 2, 
WhiskActivation.collectionName)
+
+    val activationsInPackage = (1 to 2).map { i =>
+      WhiskActivation(
+        namespace,
+        EntityName(s"xyz"),
+        creds.subject,
+        ActivationId(),
+        start = Instant.now,
+        end = Instant.now,
+        annotations = Parameters("path", s"${namespace.asString}/pkg/xyz"))
+    }.toList
+    activationsInPackage foreach { put(activationStore, _) }
+
+    waitOnView(activationStore, namespace.root, 4, WhiskActivation.view)
 
     whisk.utils.retry {
       Get(s"$collectionPath?name=xyz") ~> Route.seal(routes(creds)) ~> check {
         status should be(OK)
         val response = responseAs[List[JsObject]]
-        activations.length should be(response.length)
-        activations forall { a =>
+        val allActivations = activations ++ activationsInPackage
+        allActivations.length should be(response.length)
+        allActivations forall { a =>
           response contains a.summaryAsJson
         } should be(true)
       }
     }
+
+    // this is not yet ready, the v2 views must be activated
+    if (false) {
+      whisk.utils.retry {
+        Get(s"$collectionPath?name=pkg/xyz") ~> Route.seal(routes(creds)) ~> 
check {
+          status should be(OK)
+          val response = responseAs[List[JsObject]]
+          activationsInPackage.length should be(response.length)
+          activationsInPackage forall { a =>
+            response contains a.summaryAsJson
+          } should be(true)
+        }
+      }
+    }
   }
 
   it should "reject activation list when limit is greater than maximum allowed 
value" in {
@@ -311,8 +353,9 @@ class ActivationsApiTests extends ControllerTestCommon with 
WhiskActivationsApi
     val exceededMaxLimit = WhiskActivationsApi.maxActivationLimit + 1
     val response = Get(s"$collectionPath?limit=$exceededMaxLimit") ~> 
Route.seal(routes(creds)) ~> check {
       val response = responseAs[String]
-      response should include(
-        Messages.maxActivationLimitExceeded(exceededMaxLimit, 
WhiskActivationsApi.maxActivationLimit))
+      response should include {
+        Messages.maxActivationLimitExceeded(exceededMaxLimit, 
WhiskActivationsApi.maxActivationLimit)
+      }
       status should be(BadRequest)
     }
   }
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 a01e04f..3c77f4e 100644
--- a/tests/src/test/scala/whisk/core/database/test/DbUtils.scala
+++ b/tests/src/test/scala/whisk/core/database/test/DbUtils.scala
@@ -88,7 +88,7 @@ trait DbUtils extends TransactionCounter {
    * where the step performs a direct db query to retrieve the view and check 
the count
    * matches the given value.
    */
-  def waitOnView[Au](db: ArtifactStore[Au], namespace: EntityName, count: Int, 
viewName: String)(
+  def waitOnView[Au](db: ArtifactStore[Au], namespace: EntityName, count: Int, 
view: View)(
     implicit context: ExecutionContext,
     transid: TransactionId,
     timeout: Duration) = {
@@ -96,11 +96,10 @@ trait DbUtils extends TransactionCounter {
       () => {
         val startKey = List(namespace.asString)
         val endKey = List(namespace.asString, WhiskEntityQueries.TOP)
-        db.query(WhiskEntityQueries.viewname(viewName), startKey, endKey, 0, 
0, false, true, false, StaleParameter.No) map {
-          l =>
-            if (l.length != count) {
-              throw RetryOp()
-            } else true
+        db.query(view.name, startKey, endKey, 0, 0, false, true, false, 
StaleParameter.No) map { l =>
+          if (l.length != count) {
+            throw RetryOp()
+          } else true
         }
       },
       timeout)
diff --git a/tests/src/test/scala/whisk/core/entity/test/ViewTests.scala 
b/tests/src/test/scala/whisk/core/entity/test/ViewTests.scala
index 2347170..55b2e69 100644
--- a/tests/src/test/scala/whisk/core/entity/test/ViewTests.scala
+++ b/tests/src/test/scala/whisk/core/entity/test/ViewTests.scala
@@ -94,7 +94,7 @@ class ViewTests
     val result =
       Await.result(listAllInNamespace(store, ns.root, false, 
StaleParameter.No), dbOpTimeout).values.toList.flatten
     val expected = entities filter { _.namespace.root.toPath == ns }
-    result.length should be(expected.length)
+    result should have length expected.length
     result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
@@ -108,7 +108,7 @@ class ViewTests
         .get
         .map(e => e)
     val expected = entities filter { _.namespace.root.toPath == ns }
-    result.length should be(expected.length)
+    result should have length expected.length
     result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
@@ -120,10 +120,8 @@ class ViewTests
     }
     val expected = entities filter { !_.isInstanceOf[WhiskActivation] } filter 
{ _.namespace.root.toPath == ns }
     map.get(WhiskActivation.collectionName) should be(None)
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e.summaryAsJson
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
   def resolveListMethodForKind(kind: String) = kind match {
@@ -140,16 +138,13 @@ class ViewTests
                                             f: (WhiskEntity) => 
Boolean)(implicit entities: Seq[WhiskEntity]) = {
     implicit val tid = transid()
     val q = resolveListMethodForKind(kind)
-    val result = Await.result(q.listCollectionInNamespace(store, ns, 0, 0, 
stale = StaleParameter.No) map {
-      _.left.get.map(e => e)
-    }, dbOpTimeout)
+    val result =
+      Await.result(q.listCollectionInNamespace(store, ns, 0, 0, stale = 
StaleParameter.No).map(_.left.get), dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace.root.toPath == ns
     }
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e.summaryAsJson
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
   def getKindInNamespaceWithDoc[T](ns: EntityPath, kind: String, f: 
(WhiskEntity) => Boolean)(
@@ -158,17 +153,14 @@ class ViewTests
     val q = resolveListMethodForKind(kind)
     val result =
       Await.result(
-        q.listCollectionInNamespace(entityStore, ns, 0, 0, includeDocs = true, 
stale = StaleParameter.No) map {
-          _.right.get
-        },
+        q.listCollectionInNamespace(entityStore, ns, 0, 0, includeDocs = true, 
stale = StaleParameter.No)
+          .map(_.right.get),
         dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace.root.toPath == ns
     }
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected
   }
 
   def getKindInNamespaceByName[Au <: WhiskEntity](store: ArtifactStore[Au],
@@ -180,18 +172,14 @@ class ViewTests
     implicit val tid = transid()
     val q = resolveListMethodForKind(kind)
     val result =
-      Await.result(q.listCollectionInNamespace(store, ns.addPath(name), 0, 0, 
stale = StaleParameter.No) map {
-        _.left.get map { e =>
-          e
-        }
-      }, dbOpTimeout)
+      Await.result(
+        q.listCollectionInNamespace(store, ns.addPath(name), 0, 0, stale = 
StaleParameter.No).map(_.left.get),
+        dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace.root.toPath == ns
     }
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e.summaryAsJson
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
   def getActivationsInNamespaceByName(store: ArtifactStore[WhiskActivation],
@@ -200,36 +188,30 @@ class ViewTests
                                       f: (WhiskEntity) => Boolean)(implicit 
entities: Seq[WhiskEntity]) = {
     implicit val tid = transid()
     val result =
-      Await.result(WhiskActivation.listActivationsMatchingName(store, ns, 
name, 0, 0, stale = StaleParameter.No) map {
-        _.left.get map { e =>
-          e
-        }
-      }, dbOpTimeout)
+      Await.result(
+        WhiskActivation
+          .listActivationsMatchingName(store, ns, name.toPath, 0, 0, stale = 
StaleParameter.No)
+          .map(_.left.get),
+        dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace.root.toPath == ns
     }
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e.summaryAsJson
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
   def getKindInPackage(ns: EntityPath, kind: String, f: (WhiskEntity) => 
Boolean)(
     implicit entities: Seq[WhiskEntity]) = {
     implicit val tid = transid()
     val q = resolveListMethodForKind(kind)
-    val result = Await.result(q.listCollectionInNamespace(entityStore, ns, 0, 
0, stale = StaleParameter.No) map {
-      _.left.get map { e =>
-        e
-      }
-    }, dbOpTimeout)
+    val result = Await.result(
+      q.listCollectionInNamespace(entityStore, ns, 0, 0, stale = 
StaleParameter.No).map(_.left.get),
+      dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace == ns
     }
-    result.length should be(expected.length)
-    expected forall { e =>
-      result contains e.summaryAsJson
-    } should be(true)
+    result should have length expected.length
+    result should contain theSameElementsAs expected.map(_.summaryAsJson)
   }
 
   def getActivationsInNamespaceByNameSortedByDate(store: 
ArtifactStore[WhiskActivation],
@@ -244,16 +226,13 @@ class ViewTests
     implicit val tid = transid()
     val result = Await.result(
       WhiskActivation
-        .listActivationsMatchingName(store, ns, name, skip, count, false, 
start, end, StaleParameter.No) map {
-        _.left.get map { e =>
-          e
-        }
-      },
+        .listActivationsMatchingName(store, ns, name.toPath, skip, count, 
false, start, end, StaleParameter.No)
+        .map(_.left.get),
       dbOpTimeout)
     val expected = entities filter { e =>
       f(e) && e.namespace.root.toPath == ns
     } sortBy { case (e: WhiskActivation) => e.start.toEpochMilli; case _ => 0 
} map { _.summaryAsJson }
-    result.length should be(expected.length)
+    result should have length expected.length
     result should be(expected reverse)
   }
 
@@ -306,8 +285,8 @@ class ViewTests
       WhiskPackage(namespace2, aname(), Some(Binding(namespace1.root, 
aname()))))
 
     entities foreach { put(entityStore, _) }
-    waitOnView(entityStore, namespace1.root, 15, WhiskEntityQueries.ALL)
-    waitOnView(entityStore, namespace2.root, 14, WhiskEntityQueries.ALL)
+    waitOnView(entityStore, namespace1.root, 15, WhiskEntityQueries.viewAll)
+    waitOnView(entityStore, namespace2.root, 14, WhiskEntityQueries.viewAll)
 
     getAllInNamespace(entityStore, namespace1)
     getKindInNamespace(entityStore, namespace1, "actions", {
@@ -375,8 +354,8 @@ class ViewTests
       WhiskActivation(namespace2, actionName, Subject(), ActivationId(), start 
= now, end = now))
 
     entities foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace1.root, 2, 
WhiskActivation.collectionName)
-    waitOnView(activationStore, namespace2.root, 3, 
WhiskActivation.collectionName)
+    waitOnView(activationStore, namespace1.root, 2, WhiskActivation.view)
+    waitOnView(activationStore, namespace2.root, 3, WhiskActivation.view)
 
     getAllActivationsInNamespace(activationStore, namespace1)
     getKindInNamespace(activationStore, namespace1, "activations", {
@@ -431,7 +410,7 @@ class ViewTests
         end = now.plusSeconds(20)))
 
     entities foreach { put(activationStore, _) }
-    waitOnView(activationStore, namespace1.root, entities.length, 
WhiskActivation.collectionName)
+    waitOnView(activationStore, namespace1.root, entities.length, 
WhiskActivation.view)
 
     getActivationsInNamespaceByNameSortedByDate(
       activationStore,
@@ -472,7 +451,7 @@ class ViewTests
       Seq(WhiskAction(namespace1, aname(), jsDefault("??")), 
WhiskAction(namespace1, aname(), jsDefault("??")))
 
     entities foreach { put(entityStore, _) }
-    waitOnView(entityStore, namespace1.root, entities.length, 
WhiskEntityQueries.ALL)
+    waitOnView(entityStore, namespace1.root, entities.length, 
WhiskEntityQueries.viewAll)
     getKindInNamespaceWithDoc[WhiskAction](namespace1, "actions", {
       case (e: WhiskAction) => true
       case (_)              => false

-- 
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <commits@openwhisk.apache.org>'].

Reply via email to