-
Notifications
You must be signed in to change notification settings - Fork 154
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
Add a first test applying Scala 3 Union types #667
Add a first test applying Scala 3 Union types #667
Conversation
- Use InteractionPatternsSpec as an example for applying Scala 3's Union types to symplify actor code - Remove response message wrapper & adapter - Use the union of the actor's public protocol (the `Translate` message (the only member of the `Command` ADT) and the possible responses from the backend (messages `JobStarted`, `JobProgress`, and `JobCompleted`): `private type CommandAndResponse = Command | Backend.Response` - Instead of utilising the message adaptor `ActorRef` in the `replyTo` field of the message sent to the backend, `context.self` is used instead - The internal (extended) `Behavior[CommandAndResponse]` is narrowed to `Behavior[Command]` at creation time The diffs between the original and the new version: ```bash 136d139 < private final case class WrappedBackendResponse(response: Backend.Response) extends Command 137a141,142 > private type CommandAndResponse = Command | Backend.Response > 139,141c144 < Behaviors.setup[Command] { context => < val backendResponseMapper: ActorRef[Backend.Response] = < context.messageAdapter(rsp => WrappedBackendResponse(rsp)) --- > Behaviors.setup[CommandAndResponse] { context => 143,144c146,147 < def active(inProgress: Map[Int, ActorRef[URI]], count: Int): Behavior[Command] = { < Behaviors.receiveMessage[Command] { --- > def active(inProgress: Map[Int, ActorRef[URI]], count: Int): Behavior[CommandAndResponse] = { > Behaviors.receiveMessage[CommandAndResponse] { 147c150 < backend ! Backend.StartTranslationJob(taskId, site, backendResponseMapper) --- > backend ! Backend.StartTranslationJob(taskId, site, context.self) 150,162c153,162 < case wrapped: WrappedBackendResponse => < wrapped.response match { < case Backend.JobStarted(taskId) => < context.log.info("Started {}", taskId) < Behaviors.same < case Backend.JobProgress(taskId, progress) => < context.log.info2("Progress {}: {}", taskId, progress) < Behaviors.same < case Backend.JobCompleted(taskId, result) => < context.log.info2("Completed {}: {}", taskId, result) < inProgress(taskId) ! result < active(inProgress - taskId, count) < } --- > case Backend.JobStarted(taskId) => > context.log.info("Started {}", taskId) > Behaviors.same > case Backend.JobProgress(taskId, progress) => > context.log.info2("Progress {}: {}", taskId, progress) > Behaviors.same > case Backend.JobCompleted(taskId, result) => > context.log.info2("Completed {}: {}", taskId, result) > inProgress(taskId) ! result > active(inProgress - taskId, count) 167c167 < } --- > }.narrow ```
*/ | ||
|
||
/* | ||
* Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this code based on Lightbend code or is it your own? If it is your own, could you use a standard Apache header?
An example - https://github.com/apache/incubator-pekko/blob/main/project/AddMetaInfLicenseFiles.scala#L1-L16
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the new file is a modified version of file InteractionPatternsSpec.scala in the Pekko repo, the header is a verbatim copy of the header in that file.
I assume the Lightbend copyright header is there for a reason, unless it was left there in error. In the former case it should be kept in the new file, otherwise it should be removed in both files. Please advise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's totol new, you can let the headerCreate
sbt task to create the header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fine. It is correct to keep the headers in this case then.
Just wondering as I'm new around here. How does the link validation work or pass? I see that some PR's pass this validation but this PR doesn't even though I think it doesn't change anything wrt. links. |
@eloots It's flasky just ignore it for now, it's not related with your current PR. |
@eloots I will need more time to understand your great mind, I will do this on this weekend. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm - this is a variant on an existing test
Just wondering; if this gets merged, does this end up in the documentation automatically? |
It won't be in docs automatically. We'll need doc changes but in another PR. The idea of a Scala 3 tab won't work because the tabs are configured globally for the project. My preference would be to add a new Scala3 union type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
@eloots Thank you. Would you like to add a document for it? or we merge this pr first and you can add it later? And your blog post would be a nice addition to show how to use the typed with Scala'3 Union Type. |
Absolutely! I would like to update the Interaction patterns section and specifically the section about Adapted Response. Is there any documentation about how to update the documentation 🙂? It would be nice to add a new illustration about the changed concept of receiving responses using Union types, but I don’t know if the source of the current illustrations is available. If the new illustration could have the same look and feel that would be ideal. I can add links to the blogposts for sure. |
@eloots The doc in |
Simple markdown. I can do that ;-) |
Linked to #660
I've been looking at various tests in project
actor-typed-tests
and chose to add a test that is a refactoring of theInteractionPatternsSpec.scala
test specification as this test applies a message adapter to handle responses from other actors. Other tests to which this could be applied are:Before I would tackle any of the above, I'd like to get feedback first.
What was changed:
WrappedBackendResponse
response message wrapper &backendResponseMapper
message adapterTranslate
message (the only member of theCommand
ADT) and the possible responses from the backend (messagesJobStarted
,JobProgress
, andJobCompleted
):private type CommandAndResponse = Command | Backend.Response
ActorRef
in thereplyTo
field of the message sent to the backend,context.self
is used insteadBehavior[CommandAndResponse]
is narrowed toBehavior[Command]
at creation timeThe diffs between the original and the new version: