changing the reporting visibility of the event bus broadcast channel and removing the need to maintain an 'original channel'

This commit is contained in:
Fate-JH 2026-03-05 14:53:32 -05:00
parent f05a0ab96a
commit dbd90e6eb1
20 changed files with 44 additions and 48 deletions

View file

@ -13,7 +13,7 @@ import net.psforever.services.base.message.ObjectDelete
import scala.concurrent.duration._
final case class ReleaseEnvelope(
originalChannel: String,
channel: String,
filter: PlanetSideGUID,
msg: Release
)

View file

@ -14,7 +14,7 @@ import net.psforever.types.PlanetSideGUID
import scala.concurrent.duration._
final case class PickupItemEnvelope(
originalChannel: String,
channel: String,
filter: PlanetSideGUID,
msg: PickupItem,
zone: Zone
@ -33,7 +33,7 @@ object PickupItemEnvelope {
}
final case class DropItemEnvelope(
originalChannel: String,
channel: String,
filter: PlanetSideGUID,
msg: DropItem,
zone: Zone

View file

@ -18,11 +18,12 @@ import org.log4s.Logger
*/
trait EventSystemStamp {
/*
Example Classifiers: "foo", "foo.fizz", and "foo.buzz"
In general, Classifier channels will perform left-pattern matching.
"foo" will publish to "foo", "foo.fizz", and "foo.buzz"
To isolate "foo", one must distinguish it with a right-pattern.
"foo" is appended as "foo.bar" and no longer publishes to "foo.fizz.bar" or to "foo.buzz.bar"
Example:
The channels are "foo", "foo.fizz", and "foo.buzz"
In general, Classifier channels will perform left-pattern matching
Publishing to channel "foo" will allocate Classifiers "foo", "foo.fizz", and "foo.buzz"
To isolate "foo", one must distinguish it with a right-pattern such as "out"
Publishing to channel "foo.out" no longer publishes to "foo.fizz.out" or to "foo.buzz.out"
*/
/**
* Take an input channel and produce the publishing output channel.

View file

@ -31,7 +31,7 @@ trait CachedGenericEventEnvelope
final case class CachedEnvelope(
guid: PlanetSideGUID,
originalChannel: String,
channel: String,
filter: PlanetSideGUID,
msg: EventMessage
) extends CachedGenericEventEnvelope {

View file

@ -20,19 +20,20 @@ class GenericEventBus
type Event = GenericResponseEnvelope
type Classifier = String
protected def classify(event: Event): Classifier = event.channel
protected def classify(event: Event): Classifier = event.outChannel
/*
Example Classifiers: "foo", "foo.fizz", and "foo.buzz"
In general, Classifier channels will perform left-pattern matching.
"foo" will publish to "foo", "foo.fizz", and "foo.buzz"
Example:
The channels are "foo", "foo.fizz", and "foo.buzz"
In general, Classifier channels will perform left-pattern matching
Publishing to channel "foo" will allocate Classifiers "foo", "foo.fizz", and "foo.buzz"
See `GenericResponseEnvelope.outChannel` to determine how this is applied
*/
protected def subclassification: Subclassification[String] =
new Subclassification[Classifier] {
def isEqual(x: Classifier, y: Classifier): Boolean = x == y
protected def subclassification: Subclassification[String] = new Subclassification[Classifier] {
def isEqual(x: Classifier, y: Classifier): Boolean = x.equals(y)
def isSubclass(x: Classifier, y: Classifier): Boolean = x.startsWith(y)
}
def isSubclass(x: Classifier, y: Classifier): Boolean = x.startsWith(y)
}
override def publish(event: Event): Unit = {
super[SubchannelClassification].publish(event)

View file

@ -8,8 +8,8 @@ import net.psforever.types.PlanetSideGUID
* Defines a channel and a filter, both of which server the purpose of routing the message to its destination.
*/
trait AllEnvelopes {
/** set of subscribers on an event system bus the envelope should reach */
/** set of subscribers on an event system bus that the envelope should reach */
def channel: String
/** specific subscriber endpoint to be excluded (the subscriber should filter themselves) */
/** specific subscriber endpoint to be excluded (the subscriber should filter themselves upon receipt) */
def filter: PlanetSideGUID
}

View file

@ -7,8 +7,6 @@ import net.psforever.types.PlanetSideGUID
trait GenericMessageEnvelope
extends AllEnvelopes {
/** channel information provided with the message */
def originalChannel: String
/** input payload transported by this envelope */
def msg: EventMessage
/** method that counts as "processing" the envelope by an event system;
@ -25,6 +23,6 @@ object GenericMessageEnvelope {
* @return a tuple containing the channel, filter, and reply message
*/
def unapply(obj: GenericMessageEnvelope): Option[(String, PlanetSideGUID, EventMessage)] = {
Some((obj.originalChannel, obj.filter, obj.msg))
Some((obj.channel, obj.filter, obj.msg))
}
}

View file

@ -14,6 +14,8 @@ trait GenericResponseEnvelope
def reply: EventResponse
/** marker indicating the routing through which the original message was processed */
def stamp: EventSystemStamp
/** channel information tailored to the event system */
def outChannel: String = stamp.routing(channel)
}
object GenericResponseEnvelope {

View file

@ -14,7 +14,9 @@ case object NoReply extends EventResponse
* A stamp that represents not having been processed by an event system.
* Should never been given out to an event system.
*/
case object Undelivered extends EventSystemStamp
case object Undelivered extends EventSystemStamp {
override def routing(channel: String): String = ""
}
/**
* The mechanics of a proper event system envelope.
@ -32,16 +34,11 @@ trait MessageTransformationBehavior
extends GenericMessageEnvelope
with GenericResponseEnvelope {
private var outputStamp: EventSystemStamp = Undelivered
private var outputChannel: String = originalChannel
private var outputReply: EventResponse = NoReply
// satisfies GenericMessageEnvelope (and GenericResponseEnvelope)
def channel: String = outputChannel
// satisfies GenericMessageEnvelope
def response(stamp: EventSystemStamp): GenericResponseEnvelope = {
outputStamp = stamp
outputChannel = stamp.routing(originalChannel)
outputReply = msg.response()
this
}
@ -54,5 +51,5 @@ trait MessageTransformationBehavior
/**
* A proper event system envelope.
*/
case class MessageEnvelope(originalChannel: String, filter: PlanetSideGUID, msg: EventMessage)
case class MessageEnvelope(channel: String, filter: PlanetSideGUID, msg: EventMessage)
extends MessageTransformationBehavior

View file

@ -9,7 +9,7 @@ case object GalaxyStamp extends EventSystemStamp {
if (channel.trim.isEmpty) {
"/out"
} else {
s"/$channel/out"
super.routing(channel)
}
}
}

View file

@ -15,7 +15,7 @@ import scala.annotation.tailrec
import scala.concurrent.duration._
final case class DoorMessage(
originalChannel: String,
channel: String,
msg: IsADoorMessage,
supportMessage: Any
) extends GenericSupportEnvelope {

View file

@ -18,7 +18,7 @@ import scala.annotation.tailrec
import scala.concurrent.duration._
final case class HackEntityEnvelope(
originalChannel: String,
channel: String,
filter: PlanetSideGUID,
msg: IsAHackMessage,
supportMessage: Any

View file

@ -19,7 +19,6 @@ import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage}
import net.psforever.types._
import org.specs2.mutable.Specification
import net.psforever.services.avatar.AvatarAction
import net.psforever.services.base.envelope.MessageEnvelope
import net.psforever.services.base.message.{PlanetsideAttribute, SendResponse}
import net.psforever.services.vehicle.VehicleAction

View file

@ -17,7 +17,6 @@ import net.psforever.objects.vehicles.control.VehicleControl
import net.psforever.objects.zones.{Zone, ZoneMap}
import net.psforever.packet.game.{InventoryStateMessage, RepairMessage}
import net.psforever.types._
import net.psforever.services.avatar.AvatarAction
import net.psforever.services.base.envelope.MessageEnvelope
import net.psforever.services.base.message.{PlanetsideAttribute, SendResponse}
import net.psforever.services.vehicle.VehicleAction

View file

@ -27,7 +27,7 @@ import net.psforever.packet.game._
import net.psforever.services.ServiceManager
import net.psforever.services.base.envelope.MessageEnvelope
import net.psforever.services.base.message.{PlanetsideAttribute, SendResponse}
import net.psforever.services.vehicle.{VehicleAction, VehicleServiceMessage}
import net.psforever.services.vehicle.VehicleAction
import net.psforever.types._
import scala.concurrent.duration._

View file

@ -14,7 +14,6 @@ import net.psforever.objects.{GlobalDefinitions, Player}
import net.psforever.types.{CharacterSex, CharacterVoice, PlanetSideEmpire, PlanetSideGUID}
import org.specs2.mutable.Specification
import net.psforever.services.Service
import net.psforever.services.local.LocalService
import scala.concurrent.duration._
import akka.actor.typed.scaladsl.adapter._

View file

@ -56,7 +56,7 @@ class EnvelopeTest extends Specification {
val input = MessageEnvelope("test", TestFilter, TestMessage(5))
val output = input.response(TestStamp)
output match {
case reply @ GenericResponseEnvelope("/test/out", TestFilter, TestMessage(5)) =>
case reply @ GenericResponseEnvelope("test", TestFilter, TestMessage(5)) =>
reply.stamp mustEqual TestStamp
case _ =>
ko
@ -67,7 +67,7 @@ class EnvelopeTest extends Specification {
val input = MessageEnvelope("test", TestFilter, TestInputMessage(5))
val output = input.response(TestStamp)
output match {
case reply @ GenericResponseEnvelope("/test/out", TestFilter, TestOutputEvent(7)) =>
case reply @ GenericResponseEnvelope("test", TestFilter, TestOutputEvent(7)) =>
reply.stamp mustEqual TestStamp
case _ =>
ko
@ -79,7 +79,7 @@ class EnvelopeTest extends Specification {
"construct (quick)" in {
val input = GenericResponseEnvelope(TestStamp, "test", TestFilter, TestMessage(5))
input match {
case reply @ GenericResponseEnvelope("/test/out", TestFilter, TestMessage(5)) =>
case reply @ GenericResponseEnvelope("test", TestFilter, TestMessage(5)) =>
reply.stamp mustEqual TestStamp
case _ =>
ko

View file

@ -14,7 +14,7 @@ import scala.concurrent.duration._
object EventServiceCacheSupportTest {
final case class CachedSupportTestEnvelope(
guid: PlanetSideGUID,
originalChannel: String,
channel: String,
override val msg: EventMessage,
supportMessage: Any
) extends CachedGenericEventEnvelope with GenericSupportEnvelope {

View file

@ -92,7 +92,7 @@ class EventServiceTestNotSubscribed extends ActorTest {
events ! MessageEnvelope("test", Service.defaultPlayerGUID, TestMessage(5))
val reply = probe.receiveOne(100 milliseconds)
reply match {
case GenericResponseEnvelope("/test/out", _, TestMessage(5)) => ()
case GenericResponseEnvelope("test", _, TestMessage(5)) => ()
case _ => assert(false, "(2) message expected but not received")
}
missedProbe.expectNoMessage(100 milliseconds)
@ -127,11 +127,11 @@ class EventServiceTestLeave extends ActorTest {
events ! MessageEnvelope("anotherTest", Service.defaultPlayerGUID, TestMessage(5))
val reply1 = probe.receiveN(2, 100 milliseconds)
reply1.head match {
case GenericResponseEnvelope("/test/out", _, _) => ()
case GenericResponseEnvelope("test", _, _) => ()
case _ => assert(false, "(3) message expected but not received")
}
reply1(1) match {
case GenericResponseEnvelope("/anotherTest/out", _, _) => ()
case GenericResponseEnvelope("anotherTest", _, _) => ()
case _ => assert(false, "(4) message expected but not received")
}
@ -140,7 +140,7 @@ class EventServiceTestLeave extends ActorTest {
events ! MessageEnvelope("anotherTest", Service.defaultPlayerGUID, TestMessage(6))
val reply2 = probe.receiveOne(100 milliseconds)
reply2 match {
case GenericResponseEnvelope("/test/out", _, TestMessage(5)) => ()
case GenericResponseEnvelope("test", _, TestMessage(5)) => ()
case _ => assert(false, "(5) message expected but not received")
}
probe.expectNoMessage(250 milliseconds)
@ -161,11 +161,11 @@ class EventServiceTestLeaveAll extends ActorTest {
events ! MessageEnvelope("anotherTest", Service.defaultPlayerGUID, TestMessage(6))
val reply = probe.receiveN(2,100 milliseconds)
reply.head match {
case GenericResponseEnvelope("/test/out", _, TestMessage(5)) => ()
case GenericResponseEnvelope("test", _, TestMessage(5)) => ()
case _ => assert(false, "(6) message expected but not received")
}
reply(1) match {
case GenericResponseEnvelope("/anotherTest/out", _, TestMessage(6)) => ()
case GenericResponseEnvelope("anotherTest", _, TestMessage(6)) => ()
case _ => assert(false, "(7) message expected but not received")
}

View file

@ -29,7 +29,7 @@ object EventServiceTestBase {
}
final case class TestSupportEnvelope(
originalChannel: String,
channel: String,
msg: SupportActorRepliesWith
) extends GenericSupportEnvelope {
def filter: PlanetSideGUID = Service.defaultPlayerGUID