Skip to content

Commit e5c6af0

Browse files
Updates:
1. Only return "published" version action 2. Add max version limit
1 parent dc005b2 commit e5c6af0

File tree

10 files changed

+157
-74
lines changed

10 files changed

+157
-74
lines changed

ansible/files/whisks_design_document_for_entities_db_v2.1.0.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"reduce": "_count"
2424
},
2525
"action-versions": {
26-
"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}"
26+
"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}"
2727
}
2828
}
2929
}

common/scala/src/main/resources/application.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ kamon {
100100

101101
whisk {
102102
shared-packages-execute-only = false
103+
action-maximum-versions = 10
103104
metrics {
104105
# Enable/disable Prometheus support. If enabled then metrics would be exposed at `/metrics` endpoint
105106
# If Prometheus is enabled then please review `kamon.metric.tick-interval` (set to 1 sec by default above).

common/scala/src/main/scala/org/apache/openwhisk/core/WhiskConfig.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ object ConfigKeys {
265265

266266
val whiskConfig = "whisk.config"
267267
val sharedPackageExecuteOnly = s"whisk.shared-packages-execute-only"
268+
val actionVersionLimit = "whisk.action-maximum-versions"
268269
val swaggerUi = "whisk.swagger-ui"
269270

270271
val disableStoreResult = s"$activation.disable-store-result"

common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,10 @@ case class ExecutableWhiskActionMetaData(namespace: EntityPath,
358358

359359
}
360360

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

363363
object WhiskActionVersion {
364-
val serdes = jsonFormat4(WhiskActionVersion.apply)
364+
val serdes = jsonFormat5(WhiskActionVersion.apply)
365365
}
366366

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

387-
def get(action: FullyQualifiedEntityName, datastore: EntityStore)(
387+
def get(action: FullyQualifiedEntityName, datastore: EntityStore, fetchAll: Boolean = true)(
388388
implicit transId: TransactionId): Future[WhiskActionVersionList] = {
389389
implicit val logger: Logging = datastore.logging
390390
implicit val ec = datastore.executionContext
@@ -409,6 +409,7 @@ object WhiskActionVersionList extends MultipleReadersSingleWriterCache[WhiskActi
409409
}
410410
val mappings = values
411411
.map(WhiskActionVersion.serdes.read(_))
412+
.filter(_.publish || fetchAll)
412413
.map { actionVersion =>
413414
(actionVersion.version, actionVersion.id)
414415
}
@@ -417,6 +418,21 @@ object WhiskActionVersionList extends MultipleReadersSingleWriterCache[WhiskActi
417418
})
418419
}
419420

421+
def getMatchedDocId(action: FullyQualifiedEntityName, version: Option[SemVer], datastore: EntityStore)(
422+
implicit transId: TransactionId,
423+
ec: ExecutionContext): Future[Option[DocId]] = {
424+
get(action, datastore, version.nonEmpty).map { res =>
425+
version match {
426+
case Some(ver) =>
427+
res.versions.get(ver).map(DocId(_))
428+
case None if res.versions.nonEmpty =>
429+
Some(DocId(res.versions.maxBy(_._1)._2))
430+
case _ =>
431+
None
432+
}
433+
}
434+
}
435+
420436
// delete cache
421437
def deleteCache(action: FullyQualifiedEntityName)(implicit transId: TransactionId,
422438
ec: ExecutionContext,
@@ -620,9 +636,8 @@ object WhiskAction extends DocumentFactory[WhiskAction] with WhiskEntityQueries[
620636
val entityPath = fullyQualifiedName.path
621637
if (entityPath.defaultPackage) {
622638
// this is the default package, nothing to resolve
623-
WhiskActionVersionList.get(fullyQualifiedName, entityStore).flatMap { result =>
624-
val docId = result.matchedDocId(version).getOrElse(fullyQualifiedName.toDocId)
625-
WhiskAction.get(entityStore, docId)
639+
WhiskActionVersionList.getMatchedDocId(fullyQualifiedName, version, entityStore).flatMap { docId =>
640+
WhiskAction.get(entityStore, docId.getOrElse(fullyQualifiedName.toDocId))
626641
}
627642
} else {
628643
// there is a package to be resolved
@@ -632,9 +647,8 @@ object WhiskAction extends DocumentFactory[WhiskAction] with WhiskEntityQueries[
632647
wp flatMap { resolvedPkg =>
633648
// fully resolved name for the action
634649
val fqnAction = resolvedPkg.fullyQualifiedName(withVersion = false).add(actionName)
635-
val action = WhiskActionVersionList.get(fqnAction, entityStore).flatMap { result =>
636-
val docId = result.matchedDocId(version).getOrElse(fqnAction.toDocId)
637-
WhiskAction.get(entityStore, docId)
650+
val action = WhiskActionVersionList.getMatchedDocId(fqnAction, version, entityStore).flatMap { docId =>
651+
WhiskAction.get(entityStore, docId.getOrElse(fqnAction.toDocId))
638652
}
639653
// get the whisk action associate with it and inherit the parameters from the package/binding
640654
action map {
@@ -709,9 +723,8 @@ object WhiskActionMetaData
709723
val entityPath = fullyQualifiedName.path
710724
if (entityPath.defaultPackage) {
711725
// this is the default package, nothing to resolve
712-
WhiskActionVersionList.get(fullyQualifiedName, entityStore).flatMap { result =>
713-
val docId = result.matchedDocId(version).getOrElse(fullyQualifiedName.toDocId)
714-
WhiskActionMetaData.get(entityStore, docId)
726+
WhiskActionVersionList.getMatchedDocId(fullyQualifiedName, version, entityStore).flatMap { docId =>
727+
WhiskActionMetaData.get(entityStore, docId.getOrElse(fullyQualifiedName.toDocId))
715728
}
716729
} else {
717730
// there is a package to be resolved
@@ -721,9 +734,8 @@ object WhiskActionMetaData
721734
wp flatMap { resolvedPkg =>
722735
// fully resolved name for the action
723736
val fqnAction = resolvedPkg.fullyQualifiedName(withVersion = false).add(actionName)
724-
val action = WhiskActionVersionList.get(fqnAction, entityStore).flatMap { result =>
725-
val docId = result.matchedDocId(version).getOrElse(fqnAction.toDocId)
726-
WhiskActionMetaData.get(entityStore, docId)
737+
val action = WhiskActionVersionList.getMatchedDocId(fqnAction, version, entityStore).flatMap { docId =>
738+
WhiskActionMetaData.get(entityStore, docId.getOrElse(fqnAction.toDocId))
727739
}
728740
// get the whisk action associate with it and inherit the parameters from the package/binding
729741
action map {

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
116116
protected def executeOnly =
117117
loadConfigOrThrow[Boolean](ConfigKeys.sharedPackageExecuteOnly)
118118

119+
private val actionMaxVersionLimit =
120+
loadConfigOrThrow[Int](ConfigKeys.actionVersionLimit)
121+
119122
/** Entity normalizer to JSON object. */
120123
import RestApiCommons.emptyEntityToJsObject
121124

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

227-
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
228-
result.matchedDocId(None).getOrElse(entityName.toDocId)
229-
}
230-
231230
onComplete(checkAdditionalPrivileges) {
232231
case Success(_) =>
233-
onComplete(latestDocId) {
234-
case Success(id) =>
235-
putEntity(WhiskAction, entityStore, id, true, update(user, request) _, () => {
236-
make(user, entityName, request)
237-
}, postProcess = Some { action: WhiskAction =>
238-
WhiskActionVersionList.deleteCache(entityName)
239-
complete(OK, action)
240-
})
232+
onComplete(WhiskActionVersionList.get(entityName, entityStore)) {
233+
case Success(result) =>
234+
val id = result.matchedDocId(None).getOrElse(entityName.toDocId)
235+
putEntity(
236+
WhiskAction,
237+
entityStore,
238+
id,
239+
true,
240+
update(user, request) _,
241+
() => {
242+
make(user, entityName, request)
243+
},
244+
postProcess = Some { action: WhiskAction =>
245+
// delete oldest version when created successfully
246+
if (result.versions.size >= actionMaxVersionLimit) {
247+
val id = result.versions.minBy(_._1)._2
248+
WhiskAction.get(entityStore, DocId(id)) flatMap { entity =>
249+
WhiskAction.del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
250+
} andThen {
251+
case _ =>
252+
WhiskActionVersionList.deleteCache(entityName)
253+
}
254+
} else {
255+
WhiskActionVersionList.deleteCache(entityName)
256+
}
257+
complete(OK, action)
258+
})
241259
case Failure(f) =>
242260
terminate(InternalServerError)
243261
}
@@ -379,7 +397,7 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
379397
results.versions.values
380398
.map { id =>
381399
WhiskAction.get(entityStore, DocId(id)) flatMap { entity =>
382-
WhiskAction.del(entityStore, entity.docinfo).map(_ => entity)
400+
WhiskAction.del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
383401
}
384402
}
385403
val deleteFuture = Future.sequence(fs).andThen {
@@ -775,16 +793,16 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
775793
} else {
776794
// check whether component is a sequence or an atomic action
777795
// if the component does not exist, the future will fail with appropriate error
778-
WhiskActionVersionList.get(resolvedComponent, entityStore) flatMap { versions =>
779-
val docId = versions.matchedDocId(resolvedComponent.version).getOrElse(resolvedComponent.toDocId)
780-
WhiskAction.get(entityStore, docId) flatMap { wskComponent =>
781-
wskComponent.exec match {
782-
case SequenceExec(seqComponents) =>
783-
// sequence action, count the number of atomic actions in this sequence
784-
countAtomicActionsAndCheckCycle(origSequence, seqComponents)
785-
case _ => Future successful 1 // atomic action count is one
796+
WhiskActionVersionList.getMatchedDocId(resolvedComponent, resolvedComponent.version, entityStore) flatMap {
797+
docId =>
798+
WhiskAction.get(entityStore, docId.getOrElse(resolvedComponent.toDocId)) flatMap { wskComponent =>
799+
wskComponent.exec match {
800+
case SequenceExec(seqComponents) =>
801+
// sequence action, count the number of atomic actions in this sequence
802+
countAtomicActionsAndCheckCycle(origSequence, seqComponents)
803+
case _ => Future successful 1 // atomic action count is one
804+
}
786805
}
787-
}
788806
}
789807
}
790808
}

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Packages.scala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,14 @@ trait WhiskPackagesApi extends WhiskCollectionAPI with ReferencedEntities {
8585
}
8686
val referencedentities = referencedEntities(request)
8787

88-
// To avoid using same entity name with action
89-
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
90-
result.matchedDocId(None).getOrElse(entityName.toDocId)
91-
}
92-
9388
onComplete(entitlementProvider.check(user, Privilege.READ, referencedentities)) {
9489
case Success(_) =>
95-
onComplete(latestDocId) {
90+
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
9691
case Success(docId) =>
9792
putEntity(
9893
WhiskPackage,
9994
entityStore,
100-
docId,
95+
docId.getOrElse(entityName.toDocId),
10196
overwrite,
10297
update(request) _,
10398
() => create(request, entityName))

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Rules.scala

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,14 @@ trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
8383
parameter('overwrite ? false) { overwrite =>
8484
entity(as[WhiskRulePut]) { content =>
8585
val request = content.resolve(entityName.namespace)
86-
// To avoid using same entity name with action
87-
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
88-
result.matchedDocId(None).getOrElse(entityName.toDocId)
89-
}
9086
onComplete(entitlementProvider.check(user, Privilege.READ, referencedEntities(request))) {
9187
case Success(_) =>
92-
onComplete(latestDocId) {
88+
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
9389
case Success(docId) =>
9490
putEntity(
9591
WhiskRule,
9692
entityStore,
97-
docId,
93+
docId.getOrElse(entityName.toDocId),
9894
overwrite,
9995
update(request) _,
10096
() => {
@@ -417,15 +413,8 @@ trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
417413
}
418414

419415
actionExists <- WhiskAction.resolveAction(entityStore, action) flatMap { resolvedName =>
420-
WhiskActionVersionList.get(resolvedName, entityStore).flatMap { versions =>
421-
versions
422-
.matchedDocId(resolvedName.version)
423-
.map { docId =>
424-
WhiskActionMetaData.get(entityStore, docId)
425-
}
426-
.getOrElse {
427-
WhiskActionMetaData.get(entityStore, resolvedName.toDocId)
428-
}
416+
WhiskActionVersionList.getMatchedDocId(resolvedName, resolvedName.version, entityStore).flatMap { docId =>
417+
WhiskActionMetaData.get(entityStore, docId.getOrElse(resolvedName.toDocId))
429418
}
430419
} recoverWith {
431420
case _: NoDocumentException =>

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Triggers.scala

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,20 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
120120
override def create(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId) = {
121121
parameter('overwrite ? false) { overwrite =>
122122
entity(as[WhiskTriggerPut]) { content =>
123-
// To avoid using same entity name with action
124-
val latestDocId = WhiskActionVersionList.get(entityName, entityStore).map { result =>
125-
result.matchedDocId(None).getOrElse(entityName.toDocId)
126-
}
127-
128-
onComplete(latestDocId) {
123+
onComplete(WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore)) {
129124
case Success(docId) =>
130-
putEntity(WhiskTrigger, entityStore, docId, overwrite, update(content) _, () => {
131-
create(content, entityName)
132-
}, postProcess = Some { trigger =>
133-
completeAsTriggerResponse(trigger)
134-
})
125+
putEntity(
126+
WhiskTrigger,
127+
entityStore,
128+
docId.getOrElse(entityName.toDocId),
129+
overwrite,
130+
update(content) _,
131+
() => {
132+
create(content, entityName)
133+
},
134+
postProcess = Some { trigger =>
135+
completeAsTriggerResponse(trigger)
136+
})
135137
case Failure(f) =>
136138
terminate(InternalServerError)
137139
}

core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/PackageCollection.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,8 @@ class PackageCollection(entityStore: EntityStore)(implicit logging: Logging) ext
6363
// must determine if this is a public or owned package
6464
// or, for a binding, that it references a public or owned package
6565
val entityName = FullyQualifiedEntityName(resource.namespace.root.toPath, EntityName(pkgname))
66-
WhiskActionVersionList.get(entityName, entityStore).flatMap { result =>
67-
val docid = result.matchedDocId(None).getOrElse(entityName.toDocId)
68-
checkPackageReadPermission(namespaces, isOwner, docid)
66+
WhiskActionVersionList.getMatchedDocId(entityName, None, entityStore).flatMap { docId =>
67+
checkPackageReadPermission(namespaces, isOwner, docId.getOrElse(entityName.toDocId))
6968
}
7069
case _ => Future.successful(isOwner && allowedEntityRights.contains(right))
7170
}

0 commit comments

Comments
 (0)