Roiocam commented on code in PR #1195:
URL: https://github.com/apache/incubator-pekko/pull/1195#discussion_r1528323544


##########
actor-typed-tests/src/test/java/org/apache/pekko/actor/typed/eventstream/EventStreamSuperClassDocTest.java:
##########
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pekko.actor.typed.eventstream;
+
+import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit;
+import org.apache.pekko.actor.typed.ActorSystem;
+import org.apache.pekko.actor.typed.Behavior;
+import org.apache.pekko.actor.typed.javadsl.AbstractBehavior;
+import org.apache.pekko.actor.typed.javadsl.ActorContext;
+import org.apache.pekko.actor.typed.javadsl.Behaviors;
+import org.apache.pekko.actor.typed.javadsl.Receive;
+import org.junit.Test;
+import org.scalatestplus.junit.JUnitSuite;
+
+// #listen-to-super-class-imports
+import org.apache.pekko.actor.DeadLetter;
+import org.apache.pekko.actor.AllDeadLetters;
+import org.apache.pekko.actor.Dropped;
+import org.apache.pekko.actor.SuppressedDeadLetter;
+import org.apache.pekko.actor.UnhandledMessage;
+// #listen-to-super-class-imports
+
+public class EventStreamSuperClassDocTest extends JUnitSuite {
+
+    @Test
+    public void listenToDeadLetters() {
+        // #subscribe-to-super-class
+        ActorSystem<Command> system = 
ActorSystem.create(AllDeadLettersListenerBehavior.create(), 
"AllDeadLettersListener");
+        system.eventStream().tell(new EventStream.Subscribe<>(Command.class, 
system));
+        // #subscribe-to-super-class
+        ActorTestKit.shutdown(system);
+    }
+
+    // #listen-to-super-class
+    interface Command {}
+
+    static final class AllDeadLettersWrapper implements Command {
+        private final AllDeadLetters allDeadLetters;
+
+        public AllDeadLettersWrapper(AllDeadLetters deadLetter) {
+            this.allDeadLetters = deadLetter;
+        }
+
+        public AllDeadLetters getAllDeadLetters() {
+            return allDeadLetters;
+        }
+    }
+
+    static class AllDeadLettersListenerBehavior extends 
AbstractBehavior<Command> {
+
+        public static Behavior<Command> create() {
+            return Behaviors.setup(AllDeadLettersListenerBehavior::new);
+        }
+
+        public AllDeadLettersListenerBehavior(ActorContext<Command> context) {
+            super(context);
+        }
+
+        @Override
+        public Receive<Command> createReceive() {
+            return newReceiveBuilder().onMessage(AllDeadLettersWrapper.class, 
msg -> {
+                final AllDeadLetters allDeadLetters = msg.allDeadLetters;
+                final Class<? extends AllDeadLetters> klass = 
msg.allDeadLetters.getClass();
+                if (klass.isAssignableFrom(DeadLetter.class)) {

Review Comment:
   The actor already has done similar works on `Receive`, why do we need those 
type-checks on here?
   
   I don't think this programming style is something we want to share with 
users.
   
   In my opinion, the EventStream use case mostly was embedded Pub/Sub 
feature(aka EventBus), we treat the type as a Topic(e.g. `AllDeadLetters`), and 
the instance with subtype was the specific message(e.g. `DeadLetter`, 
`Dropped`, `UnhandledMessage`).
   
   Or a smaller range of channels: `DeadLetter` is used as both a topic and 
message instance type.
   
   In your PR, subscribing to Command doesn't make sense. When users need to 
publish, they should convert AllDeadLetter to AllDeadLetterWrapper. This is not 
the correct usage.
   
   In general, if you want this Actor to receive messages from other Actors 
(such as in your case), you can use Adapter, but it is actually like this:
   
   
   ```scala
    ActorSystem<Command> system = 
ActorSystem.create(AllDeadLettersListenerBehavior.create(), 
"AllDeadLettersListener");
   // get adapter ref, or do subscribe logic in actor internal.
   val adapterRef = system ? getAllDeadLettersAdapter
   // subscribe the raw type of `AllDeadLetters`, but receive with adapterRef
   system.eventStream().tell(new EventStream.Subscribe<>(AllDeadLetters.class, 
adapterRef));
   // and then publish look like this.
   system.eventStream().tell(new EventStream.Publish<>(DeadLetter("msg", 
senderRef, recipientRef)));
   
   // In your code, publish in this way, but in fact, you can't expect the 
producer to use the type of message that the consumer can receive. On the 
contrary, the consumer must adapt to the type of producer, which is very 
important for the ability to broadcast.
   val deadLetter = DeadLetter("msg", senderRef, recipientRef)
   system.eventStream().tell(new EventStream.Publish<>(new 
AllDeadLettersWrapper(deadLetter)));
   ```
   
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to