I am currently using API's from client A
in my controller. Sample definition of client A
:
class A @Inject()(
ws: WSClient)
{
def createSession(request: CreateSessionRequest)
: EitherT[Future, AppError, ResponseFromA] =
{
//logic. Returns ResponseFromA case class
}
}
My controller code is:
class MyController @Inject()(
a: A) {
def createSession(): Action[JsValue] =
action.async(parse.tolerantJson) { request =>
val requestValidation = for {
request <- EitherT.fromEither[Future](
checkRequest[CreateCheckout](request.body.toString, mapper))
} yield {
request
}
val createSessionResult = for {
createCheckoutInput <- requestValidation
createSessionResponse <- a.createSession(
CreateSessionRequest(createCheckoutInput))
} yield {
createSessionResponse
}
// postProcessing creates a transfer object `SessionResult`
// from `ResponseFromA`
postProcessing(createSessionResult)
}
Now I am planning to migrate to another set of API's which provide similar functionality but different response format. I have created a different client B
as follows:
class B @Inject()(
ws: WSClient)
{
def createSession(request: CreateSessionRequest)
: EitherT[Future, AppError, ResponseFromB] =
{
//logic. Returns ResponseFromB case class
}
}
Notice I have still used CreateSessionRequest
in client B
as well. This is because input to both set of API's is the same. I would like to A/B
test both set of API's. Ideally I would like to use the same controller because controller has a lot of logic which I would need to replicate if I created another controller for client B
. Response from my controller would also still be SessionResult
because I want to keep these migration changes transparent to all clients using my service.
I was looking at different design patterns like the factory pattern to conditionally select the right client to call based on some rule (say a config value which says to use client B
) but I am reaching a dead end because createSession
from both clients have different return values. I was also thinking of creating a common business object which I could use to massage the ResponseFromA
and ResponseFromB
to the common business object but that means I would need to change postProcessing(createSessionResult)
.
Any tips or pointers on how I could conditionally use client of my choice without changing controller logic too much would be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire