Skip to content

Commit

Permalink
#1434 new rcp messages using typed context and result
Browse files Browse the repository at this point in the history
  • Loading branch information
naleeha authored and keikeicheung committed Sep 5, 2024
1 parent 0bc1175 commit 065ea84
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 59 deletions.
14 changes: 10 additions & 4 deletions vuu/src/main/scala/org/finos/vuu/core/CoreServerApiHandler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,19 @@ class CoreServerApiHandler(val viewPortContainer: ViewPortContainer,
vsMsg(CloseTreeNodeSuccess(msg.vpId, msg.treeKey))(ctx)
}

override def process(msg: RpcRequest)(ctx: RequestContext): Option[ViewServerMessage] = {
val response = Try(viewPortContainer.handleRpcRequest(msg.context.viewPortId, msg.rpcName, msg.params)(ctx)) match {
override def process(msg: RpcRequest)(ctx: RequestContext): Option[ViewServerMessage] =
msg.context match {
case context: ViewPortContext => handleViewPortRpcRequest(msg, context.viewPortId, ctx)
case context => vsMsg(createErrorRpcResponse(msg, s"Unsupported request context type $context"))(ctx)
}

private def handleViewPortRpcRequest(msg: RpcRequest, viewPortId: String, ctx: RequestContext) = {
val response = Try(viewPortContainer.handleRpcRequest(viewPortId, msg.rpcName, msg.params)(ctx)) match {
case Success(functionResult) =>
logger.info(s"Processed VP RPC call ${ctx.requestId}" + msg)
functionResult match {
case RpcFunctionSuccess(data) =>
RpcResponseNew(rpcName = msg.rpcName, result = RpcResult.fromSuccess(data), NoneAction())
RpcResponseNew(rpcName = msg.rpcName, result = RpcSuccessResult(data), NoneAction())
case RpcFunctionFailure(errorCode, error, exception) =>
createErrorRpcResponse(msg, error)
}
Expand All @@ -429,7 +435,7 @@ class CoreServerApiHandler(val viewPortContainer: ViewPortContainer,
private def createErrorRpcResponse(msg: RpcRequest, errorMessage: String) = {
RpcResponseNew(
rpcName = msg.rpcName,
result = RpcResult.fromError(errorMessage),
result = RpcErrorResult(errorMessage),
action = ShowNotificationAction(NotificationType.Error, s"Failed to process ${msg.rpcName} request", errorMessage))
}
}
52 changes: 19 additions & 33 deletions vuu/src/main/scala/org/finos/vuu/net/Messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,50 +215,36 @@ case class RowUpdate(vpVersion: String, viewPortId: String, vpSize: Int, rowInde
*/

case class RpcRequest(context: RpcContext, rpcName: String, params: Any) extends MessageBody
case class RpcContext(viewPortId: String)

//case class RpcContext(viewPortId: String, rowKey: String)
//object RpcContext {
// def forViewPort(viewPortId: String) = RpcContext(viewPortId)
// def forViewPortRow(viewPortId: String, rowKey: String) = RpcContext(viewPortId)
//}
//@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
//@JsonSubTypes(Array(
// new Type(value = classOf[GlobalContext], name = "GLOBAL_CONTEXT"),
// new Type(value = classOf[ViewPortContext], name = "VIEWPORT_CONTEXT"),
// new Type(value = classOf[ViewPortRowContext], name = "VIEWPORT_ROW_CONTEXT"),
//))
//trait RpcContext
//case class GlobalContext() extends RpcContext
//case class ViewPortContext(viewPortId: String) extends RpcContext
//case class ViewPortRowContext(viewPortId: String, rowKey: String) extends RpcContext

case class RpcResponseNew(rpcName: String, result: RpcResult, action: UIAction) extends MessageBody
case class RpcResult(isSuccess: Boolean, data: Any, errorMessage: String)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(Array(
new Type(value = classOf[GlobalContext], name = "GLOBAL_CONTEXT"),
new Type(value = classOf[ViewPortContext], name = "VIEWPORT_CONTEXT"),
new Type(value = classOf[ViewPortRowContext], name = "VIEWPORT_ROW_CONTEXT"),
))
trait RpcContext
case class GlobalContext() extends RpcContext
case class ViewPortContext(viewPortId: String) extends RpcContext
case class ViewPortRowContext(viewPortId: String, rowKey: String) extends RpcContext

object RpcResult {
def fromError(errorMessage: String): RpcResult = RpcResult(isSuccess = false, data = null, errorMessage = errorMessage)
def fromSuccess(data: Any): RpcResult = RpcResult(isSuccess = true, data = data, errorMessage = null)
}
case class RpcResponseNew(rpcName: String, result: RpcResult, action: UIAction) extends MessageBody

//@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
//@JsonSubTypes(Array(
// new Type(value = classOf[RpcSuccessResult], name = "SUCCESS_RESULT"),
// new Type(value = classOf[RpcErrorResult], name = "ERROR_RESULT"),
//))
//trait RpcResult
//case class RpcSuccessResult(data: Any) extends RpcResult
//case class RpcErrorResult(errorMessage: String) extends RpcResult
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(Array(
new Type(value = classOf[RpcSuccessResult], name = "SUCCESS_RESULT"),
new Type(value = classOf[RpcErrorResult], name = "ERROR_RESULT"),
))
trait RpcResult
case class RpcSuccessResult(data: Any) extends RpcResult
case class RpcErrorResult(errorMessage: String) extends RpcResult

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes(Array(
new Type(value = classOf[NoneAction], name = "NO_ACTION"),
new Type(value = classOf[ShowNotificationAction], name = "SHOW_NOTIFICATION_ACTION"),
))
trait UIAction

case class NoneAction() extends UIAction

case class ShowNotificationAction(notificationType: String, title: String, message: String) extends UIAction

object NotificationType {
Expand Down
45 changes: 23 additions & 22 deletions vuu/src/test/scala/org/finos/vuu/wsapi/TypeAheadWSApiTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {
val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"

responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List("12355", "45321", "89564", "42262", "65879", "88875", "45897", "23564", "33657", "99854")
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List("12355", "45321", "89564", "42262", "65879", "88875", "45897", "23564", "33657", "99854")

And("return No Action")
responseBody.action shouldBe a[NoneAction]
Expand All @@ -56,8 +56,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValuesStartingWith"
responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List("Tom Sawyer", "Tom Thatcher")
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List("Tom Sawyer", "Tom Thatcher")
}

Scenario("Start with a specified string that has no matching value") {
Expand All @@ -74,8 +74,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValuesStartingWith"
responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List.empty
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List.empty
}

Scenario("For a column that is not in view port") {
Expand All @@ -92,8 +92,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"
responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List.empty
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List.empty
}

Scenario("For a column that does not exist") {
Expand All @@ -110,8 +110,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"
responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List.empty
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List.empty
}

Scenario("For a viewport that does not exist") {
Expand All @@ -126,9 +126,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {
val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"

responseBody.result.isSuccess shouldEqual false
responseBody.result.errorMessage shouldEqual "No viewport viewPortThatDoesNotExist found for RPC Call for getUniqueFieldValues"
//todo responseBody.result.data should be(null)
val result = assertAndCastAsInstanceOf[RpcErrorResult](responseBody.result)
result.errorMessage shouldEqual "No viewport viewPortThatDoesNotExist found for RPC Call for getUniqueFieldValues"

And("Show error notification action")
val action = assertAndCastAsInstanceOf[ShowNotificationAction](responseBody.action)
Expand All @@ -151,8 +150,8 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

val responseBody = assertBodyIsInstanceOf[RpcResponseNew](response)
responseBody.rpcName shouldEqual "getUniqueFieldValues"
responseBody.result.isSuccess shouldEqual true
responseBody.result.data shouldEqual List.empty
val result = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody.result)
result.data shouldEqual List.empty
}

Scenario("When there is multiple viewports and multiple requests") {
Expand All @@ -167,15 +166,17 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {
val requestId1 = vuuClient.send(sessionId, tokenId, getTypeAheadRequest1)
val requestId2 = vuuClient.send(sessionId, tokenId, getTypeAheadRequest2)


Then("return success response for each request")
val response1 = vuuClient.awaitForResponse(requestId1)
val response2 = vuuClient.awaitForResponse(requestId2)

val responseBody1 = assertBodyIsInstanceOf[RpcResponseNew](response1)
val result1 = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody1.result)

val response2 = vuuClient.awaitForResponse(requestId2)
val responseBody2 = assertBodyIsInstanceOf[RpcResponseNew](response2)
responseBody1.result.data shouldEqual List("Sid Sawyer", "Sally Phelps")
responseBody2.result.data shouldEqual List("Tom Sawyer", "Tom Thatcher")
val result2 = assertAndCastAsInstanceOf[RpcSuccessResult](responseBody2.result)

result1.data shouldEqual List("Sid Sawyer", "Sally Phelps")
result2.data shouldEqual List("Tom Sawyer", "Tom Thatcher")
}
}

Expand Down Expand Up @@ -245,7 +246,7 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

private def createTypeAheadRequest(viewPortId: String, tableName: String, columnName: String): RpcRequest = {
RpcRequest(
RpcContext(viewPortId),
ViewPortContext(viewPortId),
RpcNames.UniqueFieldValuesRpc,
params = Map(
"table" -> tableName,
Expand All @@ -256,7 +257,7 @@ class TypeAheadWSApiTest extends WebSocketApiTestBase {

private def createTypeAheadStartWithRequest(viewPortId: String, tableName: String, columnName: String, startString: String): RpcRequest = {
RpcRequest(
RpcContext(viewPortId),
ViewPortContext(viewPortId),
RpcNames.UniqueFieldValuesStartWithRpc,
params = Map(
"table" -> tableName,
Expand Down

0 comments on commit 065ea84

Please sign in to comment.