Skip to content

Commit

Permalink
Updates:
Browse files Browse the repository at this point in the history
1. Only return "published" version action
2. Add max version limit
  • Loading branch information
jiangpengcheng committed Oct 9, 2020
1 parent dc005b2 commit e5c6af0
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"reduce": "_count"
},
"action-versions": {
"map": "function (doc) {\n var isAction = function (doc) { return (doc.exec !== undefined) };\n if (isAction(doc)) try {\n var value = {\n namespace: doc.namespace,\n name: doc.name,\n id: doc._id,\n version: doc.version,\n };\n emit([doc.namespace + \"/\" + doc.name], value);\n } catch (e) {}\n}"
"map": "function (doc) {\n var isAction = function (doc) { return (doc.exec !== undefined) };\n if (isAction(doc)) try {\n var published = true;\n doc.annotations.forEach(function(anno) {\n if(anno[\"key\"] == \"publish\")\n published = anno[\"value\"]\n });\n \n var value = {\n namespace: doc.namespace,\n name: doc.name,\n _id: doc._id,\n version: doc.version,\n publish: published,\n };\n var versions = doc.version.split(\".\")\n emit([doc.namespace + \"/\" + doc.name], value);\n } catch (e) {}\n}"
}
}
}
1 change: 1 addition & 0 deletions common/scala/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ kamon {

whisk {
shared-packages-execute-only = false
action-maximum-versions = 10
metrics {
# Enable/disable Prometheus support. If enabled then metrics would be exposed at `/metrics` endpoint
# If Prometheus is enabled then please review `kamon.metric.tick-interval` (set to 1 sec by default above).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ object ConfigKeys {

val whiskConfig = "whisk.config"
val sharedPackageExecuteOnly = s"whisk.shared-packages-execute-only"
val actionVersionLimit = "whisk.action-maximum-versions"
val swaggerUi = "whisk.swagger-ui"

val disableStoreResult = s"$activation.disable-store-result"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,10 @@ case class ExecutableWhiskActionMetaData(namespace: EntityPath,

}

case class WhiskActionVersion(id: String, namespace: EntityPath, name: EntityName, version: SemVer)
case class WhiskActionVersion(id: String, namespace: EntityPath, name: EntityName, version: SemVer, publish: Boolean)

object WhiskActionVersion {
val serdes = jsonFormat4(WhiskActionVersion.apply)
val serdes = jsonFormat5(WhiskActionVersion.apply)
}

case class WhiskActionVersionList(namespace: EntityPath, name: EntityName, versions: Map[SemVer, String]) {
Expand All @@ -384,7 +384,7 @@ object WhiskActionVersionList extends MultipleReadersSingleWriterCache[WhiskActi
CacheKey(action.fullPath.asString)
}

def get(action: FullyQualifiedEntityName, datastore: EntityStore)(
def get(action: FullyQualifiedEntityName, datastore: EntityStore, fetchAll: Boolean = true)(
implicit transId: TransactionId): Future[WhiskActionVersionList] = {
implicit val logger: Logging = datastore.logging
implicit val ec = datastore.executionContext
Expand All @@ -409,6 +409,7 @@ object WhiskActionVersionList extends MultipleReadersSingleWriterCache[WhiskActi
}
val mappings = values
.map(WhiskActionVersion.serdes.read(_))
.filter(_.publish || fetchAll)
.map { actionVersion =>
(actionVersion.version, actionVersion.id)
}
Expand All @@ -417,6 +418,21 @@ object WhiskActionVersionList extends MultipleReadersSingleWriterCache[WhiskActi
})
}

def getMatchedDocId(action: FullyQualifiedEntityName, version: Option[SemVer], datastore: EntityStore)(
implicit transId: TransactionId,
ec: ExecutionContext): Future[Option[DocId]] = {
get(action, datastore, version.nonEmpty).map { res =>
version match {
case Some(ver) =>
res.versions.get(ver).map(DocId(_))
case None if res.versions.nonEmpty =>
Some(DocId(res.versions.maxBy(_._1)._2))
case _ =>
None
}
}
}

// delete cache
def deleteCache(action: FullyQualifiedEntityName)(implicit transId: TransactionId,
ec: ExecutionContext,
Expand Down Expand Up @@ -620,9 +636,8 @@ object WhiskAction extends DocumentFactory[WhiskAction] with WhiskEntityQueries[
val entityPath = fullyQualifiedName.path
if (entityPath.defaultPackage) {
// this is the default package, nothing to resolve
WhiskActionVersionList.get(fullyQualifiedName, entityStore).flatMap { result =>
val docId = result.matchedDocId(version).getOrElse(fullyQualifiedName.toDocId)
WhiskAction.get(entityStore, docId)
WhiskActionVersionList.getMatchedDocId(fullyQualifiedName, version, entityStore).flatMap { docId =>
WhiskAction.get(entityStore, docId.getOrElse(fullyQualifiedName.toDocId))
}
} else {
// there is a package to be resolved
Expand All @@ -632,9 +647,8 @@ object WhiskAction extends DocumentFactory[WhiskAction] with WhiskEntityQueries[
wp flatMap { resolvedPkg =>
// fully resolved name for the action
val fqnAction = resolvedPkg.fullyQualifiedName(withVersion = false).add(actionName)
val action = WhiskActionVersionList.get(fqnAction, entityStore).flatMap { result =>
val docId = result.matchedDocId(version).getOrElse(fqnAction.toDocId)
WhiskAction.get(entityStore, docId)
val action = WhiskActionVersionList.getMatchedDocId(fqnAction, version, entityStore).flatMap { docId =>
WhiskAction.get(entityStore, docId.getOrElse(fqnAction.toDocId))
}
// get the whisk action associate with it and inherit the parameters from the package/binding
action map {
Expand Down Expand Up @@ -709,9 +723,8 @@ object WhiskActionMetaData
val entityPath = fullyQualifiedName.path
if (entityPath.defaultPackage) {
// this is the default package, nothing to resolve
WhiskActionVersionList.get(fullyQualifiedName, entityStore).flatMap { result =>
val docId = result.matchedDocId(version).getOrElse(fullyQualifiedName.toDocId)
WhiskActionMetaData.get(entityStore, docId)
WhiskActionVersionList.getMatchedDocId(fullyQualifiedName, version, entityStore).flatMap { docId =>
WhiskActionMetaData.get(entityStore, docId.getOrElse(fullyQualifiedName.toDocId))
}
} else {
// there is a package to be resolved
Expand All @@ -721,9 +734,8 @@ object WhiskActionMetaData
wp flatMap { resolvedPkg =>
// fully resolved name for the action
val fqnAction = resolvedPkg.fullyQualifiedName(withVersion = false).add(actionName)
val action = WhiskActionVersionList.get(fqnAction, entityStore).flatMap { result =>
val docId = result.matchedDocId(version).getOrElse(fqnAction.toDocId)
WhiskActionMetaData.get(entityStore, docId)
val action = WhiskActionVersionList.getMatchedDocId(fqnAction, version, entityStore).flatMap { docId =>
WhiskActionMetaData.get(entityStore, docId.getOrElse(fqnAction.toDocId))
}
// get the whisk action associate with it and inherit the parameters from the package/binding
action map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
protected def executeOnly =
loadConfigOrThrow[Boolean](ConfigKeys.sharedPackageExecuteOnly)

private val actionMaxVersionLimit =
loadConfigOrThrow[Int](ConfigKeys.actionVersionLimit)

/** Entity normalizer to JSON object. */
import RestApiCommons.emptyEntityToJsObject

Expand Down Expand Up @@ -224,20 +227,35 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
case _ => entitlementProvider.check(user, content.exec)
}

val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
result.matchedDocId(None).getOrElse(entityName.toDocId)
}

onComplete(checkAdditionalPrivileges) {
case Success(_) =>
onComplete(latestDocId) {
case Success(id) =>
putEntity(WhiskAction, entityStore, id, true, update(user, request) _, () => {
make(user, entityName, request)
}, postProcess = Some { action: WhiskAction =>
WhiskActionVersionList.deleteCache(entityName)
complete(OK, action)
})
onComplete(WhiskActionVersionList.get(entityName, entityStore)) {
case Success(result) =>
val id = result.matchedDocId(None).getOrElse(entityName.toDocId)
putEntity(
WhiskAction,
entityStore,
id,
true,
update(user, request) _,
() => {
make(user, entityName, request)
},
postProcess = Some { action: WhiskAction =>
// delete oldest version when created successfully
if (result.versions.size >= actionMaxVersionLimit) {
val id = result.versions.minBy(_._1)._2
WhiskAction.get(entityStore, DocId(id)) flatMap { entity =>
WhiskAction.del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
} andThen {
case _ =>
WhiskActionVersionList.deleteCache(entityName)
}
} else {
WhiskActionVersionList.deleteCache(entityName)
}
complete(OK, action)
})
case Failure(f) =>
terminate(InternalServerError)
}
Expand Down Expand Up @@ -379,7 +397,7 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
results.versions.values
.map { id =>
WhiskAction.get(entityStore, DocId(id)) flatMap { entity =>
WhiskAction.del(entityStore, entity.docinfo).map(_ => entity)
WhiskAction.del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
}
}
val deleteFuture = Future.sequence(fs).andThen {
Expand Down Expand Up @@ -775,16 +793,16 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
} else {
// check whether component is a sequence or an atomic action
// if the component does not exist, the future will fail with appropriate error
WhiskActionVersionList.get(resolvedComponent, entityStore) flatMap { versions =>
val docId = versions.matchedDocId(resolvedComponent.version).getOrElse(resolvedComponent.toDocId)
WhiskAction.get(entityStore, docId) flatMap { wskComponent =>
wskComponent.exec match {
case SequenceExec(seqComponents) =>
// sequence action, count the number of atomic actions in this sequence
countAtomicActionsAndCheckCycle(origSequence, seqComponents)
case _ => Future successful 1 // atomic action count is one
WhiskActionVersionList.getMatchedDocId(resolvedComponent, resolvedComponent.version, entityStore) flatMap {
docId =>
WhiskAction.get(entityStore, docId.getOrElse(resolvedComponent.toDocId)) flatMap { wskComponent =>
wskComponent.exec match {
case SequenceExec(seqComponents) =>
// sequence action, count the number of atomic actions in this sequence
countAtomicActionsAndCheckCycle(origSequence, seqComponents)
case _ => Future successful 1 // atomic action count is one
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,14 @@ trait WhiskPackagesApi extends WhiskCollectionAPI with ReferencedEntities {
}
val referencedentities = referencedEntities(request)

// To avoid using same entity name with action
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
result.matchedDocId(None).getOrElse(entityName.toDocId)
}

onComplete(entitlementProvider.check(user, Privilege.READ, referencedentities)) {
case Success(_) =>
onComplete(latestDocId) {
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
case Success(docId) =>
putEntity(
WhiskPackage,
entityStore,
docId,
docId.getOrElse(entityName.toDocId),
overwrite,
update(request) _,
() => create(request, entityName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,14 @@ trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
parameter('overwrite ? false) { overwrite =>
entity(as[WhiskRulePut]) { content =>
val request = content.resolve(entityName.namespace)
// To avoid using same entity name with action
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
result.matchedDocId(None).getOrElse(entityName.toDocId)
}
onComplete(entitlementProvider.check(user, Privilege.READ, referencedEntities(request))) {
case Success(_) =>
onComplete(latestDocId) {
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
case Success(docId) =>
putEntity(
WhiskRule,
entityStore,
docId,
docId.getOrElse(entityName.toDocId),
overwrite,
update(request) _,
() => {
Expand Down Expand Up @@ -417,15 +413,8 @@ trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
}

actionExists <- WhiskAction.resolveAction(entityStore, action) flatMap { resolvedName =>
WhiskActionVersionList.get(resolvedName, entityStore).flatMap { versions =>
versions
.matchedDocId(resolvedName.version)
.map { docId =>
WhiskActionMetaData.get(entityStore, docId)
}
.getOrElse {
WhiskActionMetaData.get(entityStore, resolvedName.toDocId)
}
WhiskActionVersionList.getMatchedDocId(resolvedName, resolvedName.version, entityStore).flatMap { docId =>
WhiskActionMetaData.get(entityStore, docId.getOrElse(resolvedName.toDocId))
}
} recoverWith {
case _: NoDocumentException =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,18 +120,20 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
override def create(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId) = {
parameter('overwrite ? false) { overwrite =>
entity(as[WhiskTriggerPut]) { content =>
// To avoid using same entity name with action
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
result.matchedDocId(None).getOrElse(entityName.toDocId)
}

onComplete(latestDocId) {
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
case Success(docId) =>
putEntity(WhiskTrigger, entityStore, docId, overwrite, update(content) _, () => {
create(content, entityName)
}, postProcess = Some { trigger =>
completeAsTriggerResponse(trigger)
})
putEntity(
WhiskTrigger,
entityStore,
docId.getOrElse(entityName.toDocId),
overwrite,
update(content) _,
() => {
create(content, entityName)
},
postProcess = Some { trigger =>
completeAsTriggerResponse(trigger)
})
case Failure(f) =>
terminate(InternalServerError)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ class PackageCollection(entityStore: EntityStore)(implicit logging: Logging) ext
// must determine if this is a public or owned package
// or, for a binding, that it references a public or owned package
val entityName = FullyQualifiedEntityName(resource.namespace.root.toPath, EntityName(pkgname))
WhiskActionVersionList.get(entityName, entityStore).flatMap { result =>
val docid = result.matchedDocId(None).getOrElse(entityName.toDocId)
checkPackageReadPermission(namespaces, isOwner, docid)
WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore).flatMap { docId =>
checkPackageReadPermission(namespaces, isOwner, docId.getOrElse(entityName.toDocId))
}
case _ => Future.successful(isOwner && allowedEntityRights.contains(right))
}
Expand Down
Loading

0 comments on commit e5c6af0

Please sign in to comment.