Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove isSubprocess and ProcessAction backward compatibility #4602

Merged
merged 2 commits into from Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -19,25 +19,7 @@ object processdetails {

val StateActionsTypes: Set[ProcessActionType] = Set(Cancel, Deploy, Pause)

//TODO needed for compatibility, could be removed in NU 1.12
private def handleBothIsFragmentIsSubprocessInDecoder(aCursor: ACursor): ACursor = {
aCursor.withFocus(_.mapObject { jsonObject =>
val isFragment = jsonObject("isSubprocess").orElse(jsonObject("isFragment")).flatMap(_.asBoolean).getOrElse(throw new IllegalArgumentException("Missing any of [.isSubprocess, .isFragment] fields"))
jsonObject.add("isFragment", Json.fromBoolean(isFragment))
})
}

private def handleBothIsFragmentIsSubprocessInEncoder(jsonObject: JsonObject): JsonObject = {
val isFragment = jsonObject("isFragment").flatMap(_.asBoolean).getOrElse(throw new IllegalArgumentException("Missing field .isFragment"))
jsonObject.add("isSubprocess", Json.fromBoolean(isFragment))
}

object BasicProcess {

implicit def encoder: Encoder[BasicProcess] = deriveConfiguredEncoder[BasicProcess].mapJsonObject(handleBothIsFragmentIsSubprocessInEncoder)

implicit def decoder: Decoder[BasicProcess] = deriveConfiguredDecoder[BasicProcess].prepare(handleBothIsFragmentIsSubprocessInDecoder)

def apply[ProcessShape](baseProcessDetails: BaseProcessDetails[ProcessShape]) = new BasicProcess(
id = baseProcessDetails.id,
name = ProcessName(baseProcessDetails.name),
Expand All @@ -59,32 +41,32 @@ object processdetails {
)
}

case class BasicProcess(id: String,
name: ProcessName,
processId: ApiProcessId,
processVersionId: VersionId,
isArchived: Boolean,
isFragment: Boolean,
processCategory: String,
processingType: ProcessingType,
modificationDate: Instant,
modifiedAt: Instant,
modifiedBy: String,
createdAt: Instant,
createdBy: String,
lastAction: Option[ProcessAction],
lastStateAction: Option[ProcessAction],
lastDeployedAction: Option[ProcessAction],
// "State" is empty only for a while - just after fetching from DB, after that it is is filled by state computed based on DeploymentManager state.
// After that it remains always defined.
state: Option[ProcessState] = Option.empty
)
@JsonCodec case class BasicProcess(id: String,
name: ProcessName,
processId: ApiProcessId,
processVersionId: VersionId,
isArchived: Boolean,
isFragment: Boolean,
processCategory: String,
processingType: ProcessingType,
modificationDate: Instant,
modifiedAt: Instant,
modifiedBy: String,
createdAt: Instant,
createdBy: String,
lastAction: Option[ProcessAction],
lastStateAction: Option[ProcessAction],
lastDeployedAction: Option[ProcessAction],
// "State" is empty only for a while - just after fetching from DB, after that it is is filled by state computed based on DeploymentManager state.
// After that it remains always defined.
state: Option[ProcessState] = Option.empty
)

object BaseProcessDetails {
//It's necessary to encode / decode ProcessState
implicit def encoder[T](implicit shape: Encoder[T]): Encoder[BaseProcessDetails[T]] = deriveConfiguredEncoder[BaseProcessDetails[T]].mapJsonObject(handleBothIsFragmentIsSubprocessInEncoder)
implicit def encoder[T](implicit shape: Encoder[T]): Encoder[BaseProcessDetails[T]] = deriveConfiguredEncoder

implicit def decoder[T](implicit shape: Decoder[T]): Decoder[BaseProcessDetails[T]] = deriveConfiguredDecoder[BaseProcessDetails[T]].prepare(handleBothIsFragmentIsSubprocessInDecoder)
implicit def decoder[T](implicit shape: Decoder[T]): Decoder[BaseProcessDetails[T]] = deriveConfiguredDecoder
}

case class BaseProcessDetails[ProcessShape](id: String, //It temporary holds the name of process, because it's used everywhere in GUI - TODO: change type to ProcessId and explicitly use processName
Expand Down

This file was deleted.

Expand Up @@ -49,21 +49,6 @@ class DefinitionResources(modelDataProvider: ProcessingTypeDataProvider[ModelDat
processingTypeData.additionalPropertiesConfig,
processingType)
)
//TODO remove isSubprocess param path after NU 1.10 release
} ~ parameter(Symbol("isSubprocess").as[Boolean]) { isSubprocess =>
val fragments = fragmentRepository.loadFragments(Map.empty)
complete(
UIProcessObjectsFactory.prepareUIProcessObjects(
processingTypeData.modelData,
processingTypeData.staticObjectsDefinition,
processingTypeData.deploymentManager,
user,
fragments,
isFragment = isSubprocess,
processCategoryService,
processingTypeData.additionalPropertiesConfig,
processingType)
)
}
}
} ~ dictResources.route(processingTypeData.modelData)
Expand Down
Expand Up @@ -198,12 +198,11 @@ class ProcessesResources(
authorize(user.can(category, Permission.Write)) {
optionalHeaderValue(RemoteUserName.extractFromHeader) { remoteUserName =>
canOverrideUsername(category, remoteUserName)(user) {
//TODO change it to `parameters(Symbol("isFragment") ? false)` after NU 1.10 release
parameters(Symbol("isFragment").as[Boolean].optional, Symbol("isSubprocess").withDefault(false)) { (isFragment, isSubprocess) =>
parameters(Symbol("isFragment") ? false) { isFragment =>
post {
complete {
processService
.createProcess(CreateProcessCommand(ProcessName(processName), category, isFragment.getOrElse(isSubprocess), remoteUserName))
.createProcess(CreateProcessCommand(ProcessName(processName), category, isFragment, remoteUserName))
.withSideEffect(response => sideEffectAction(response) { process =>
OnSaved(process.id, process.versionId)
})
Expand Down Expand Up @@ -326,7 +325,6 @@ class ProcessesResources(
private def processesQuery: Directive1[ProcessesQuery] = {
parameters(
Symbol("isFragment").as[Boolean].?,
Symbol("isSubprocess").as[Boolean].?, //TODO remove `isSubprocess` after NU 1.10 release
Symbol("isArchived").as[Boolean].?,
Symbol("isDeployed").as[Boolean].?,
Symbol("categories").as(CsvSeq[String]).?,
Expand All @@ -344,15 +342,14 @@ object ProcessesResources {
case class UnmarshallError(message: String) extends Exception(message) with FatalError

case class ProcessesQuery(isFragment: Option[Boolean],
isSubprocess: Option[Boolean],
isArchived: Option[Boolean],
isDeployed: Option[Boolean],
categories: Option[Seq[String]],
processingTypes: Option[Seq[String]],
names: Option[Seq[String]],
) {
def toRepositoryQuery: FetchProcessesDetailsQuery = FetchProcessesDetailsQuery(
isFragment = isFragment.orElse(isSubprocess),
isFragment = isFragment,
isArchived = isArchived,
isDeployed = isDeployed,
categories = categories,
Expand All @@ -362,6 +359,6 @@ object ProcessesResources {
}

object ProcessesQuery {
def empty: ProcessesQuery = ProcessesQuery(None, None, None, None, None, None, None)
def empty: ProcessesQuery = ProcessesQuery(None, None, None, None, None, None)
}
}
Expand Up @@ -134,8 +134,7 @@ trait StandardRemoteEnvironment extends FailFastCirceSupport with RemoteEnvironm
EitherT {
invokeForSuccess(
HttpMethods.POST, List("processes", localProcess.id, category),
//TODO replace `isSubprocess` with `isFragment` after 1.10 release
Query(("isSubprocess", localProcess.metaData.isFragment.toString)), HttpEntity.Empty, remoteUserNameHeader
Query(("isFragment", localProcess.metaData.isFragment.toString)), HttpEntity.Empty, remoteUserNameHeader
)
}
}
Expand Down
Expand Up @@ -81,7 +81,7 @@ class StandardRemoteEnvironmentSpec extends AnyFlatSpec with Matchers with Patie
object AddProcess {
def unapply(arg: (String, HttpMethod)): Option[Boolean] = {
if (is(s"/processes/${expectedProcessDetails.id}/$expectedProcessCategory", POST)) {
uri.query().get("isFragment").map(_.toBoolean).orElse(uri.query().get("isSubprocess").map(_.toBoolean)).orElse(Some(false))
uri.query().get("isFragment").map(_.toBoolean).orElse(Some(false))
} else {
None
}
Expand Down
1 change: 1 addition & 0 deletions docs/Changelog.md
Expand Up @@ -2,6 +2,7 @@

1.12.0 (Not released yet)
-------------------------
* [#4602](https://github.com/TouK/nussknacker/pull/4602) Cleaning subprocess usages after NU 1.11 release
* [#4582](https://github.com/TouK/nussknacker/pull/4582) Fixed: Releasing app resources on the designer close
* [#4540](https://github.com/TouK/nussknacker/pull/4540) Improvement: Allow selecting a claim from OIDC JWT to represent the username
* [#4555](https://github.com/TouK/nussknacker/pull/4555) Remove: Back compatibility for encoding/decoding UIParameter
Expand Down
3 changes: 3 additions & 0 deletions docs/MigrationGuide.md
Expand Up @@ -13,6 +13,9 @@ To see the biggest differences please consult the [changelog](Changelog.md).
* `KafkaClient.sendMessage` accepts generic content with json encoder

### REST API changes
* [#4602](https://github.com/TouK/nussknacker/pull/4602) Cleaning subprocess usages after NU 1.11 release
* Removed isSubprocess endpoint param, use isFragment from now on.
* Removed backward compatibility for subprocess fields.

### Other changes
* [#4492](https://github.com/TouK/nussknacker/pull/4492) Allow to test fragments using ad hoc testing.
Expand Down
@@ -1,19 +1,15 @@
package pl.touk.nussknacker.engine.api.deployment

import io.circe.Decoder.Result
import io.circe.{Decoder, Encoder, HCursor}
import io.circe.{Decoder, Encoder}
import io.circe.generic.JsonCodec
import io.circe.generic.semiauto.deriveEncoder
import pl.touk.nussknacker.engine.api.deployment
import pl.touk.nussknacker.engine.api.deployment.ProcessActionState.ProcessActionState
import pl.touk.nussknacker.engine.api.deployment.ProcessActionType.ProcessActionType
import pl.touk.nussknacker.engine.api.process.{ProcessId, VersionId}

import java.time.Instant
import java.util.UUID
import scala.util.Random

case class ProcessAction(id: ProcessActionId,
@JsonCodec case class ProcessAction(id: ProcessActionId,
processId: ProcessId,
// We use process action only for finished/execution finished actions so processVersionId is always defined
processVersionId: VersionId,
Expand All @@ -28,52 +24,6 @@ case class ProcessAction(id: ProcessActionId,
comment: Option[String],
buildInfo: Map[String, String])

//TODO remove it in NU 1.12 and restore @JsonCodec
object ProcessAction {
//custom decoder for compatibility reasons
implicit val decodeProcessAction: Decoder[ProcessAction] = new Decoder[ProcessAction] {
override def apply(c: HCursor): Result[ProcessAction] =
for {
id <- c.downField("id").as[ProcessActionId] match {
//dummy UUID for backward compatibility
case Left(_) => Right(ProcessActionId(new UUID(0, 0)))
case Right(id) => Right(id)
}
processId <- c.downField("processId").as[ProcessId] match {
//dummy value for backeard compatibility
case Left(_) => Right(ProcessId(0L))
case Right(processId) => Right(processId)
}
processVersionId <- c.downField("processVersionId").as[VersionId]
user <- c.downField("user").as[String]
createdAt <- c.downField("createdAt").as[Instant] match {
//dummy value for backward compatibility
case Left(_) => Right(Instant.now())
case Right(createdAt) => Right(createdAt)
}
performedAt <- c.downField("performedAt").as[Instant]
actionType <- c.downField("actionType").as[ProcessActionType] match {
case Left(_) => c.downField("action").as[ProcessActionType]
case Right(actionType) => Right(actionType)
}
state <- c.downField("state").as[ProcessActionState] match {
//dummy value for backward compatibility
case Left(_) => Right(ProcessActionState.InProgress)
case Right(state) => Right(state)
}
failureMessage <- c.downField("failureMessage").as[Option[String]] match {
case Left(_) => Right(None)
case Right(failureMessage) => Right(failureMessage)
}
commentId <- c.downField("commentId").as[Option[Long]]
comment <- c.downField("comment").as[Option[String]]
buildInfo <- c.downField("buildInfo").as[Map[String, String]]
} yield ProcessAction(id, processId, processVersionId, user, createdAt, performedAt, actionType, state, failureMessage, commentId, comment, buildInfo)
}

implicit val encodeProcessAction: Encoder[ProcessAction] = deriveEncoder[ProcessAction]
}

final case class ProcessActionId(value: UUID) {
override def toString: String = value.toString
}
Expand Down