Separate bus messages from pipeline frames

BusMessage was a mixin tacked onto DataFrame / SystemFrame so the bus
could reuse the frame priority machinery. That made every bus message
also a Frame, which is misleading — bus messages travel on the bus, not
through pipelines. If a worker actually needs to ship a frame, it wraps
it in BusFrameMessage.

BusMessage is now a plain dataclass base carrying source/target.
BusDataMessage and BusSystemMessage are empty subclasses that exist
only as priority markers. The bus router and the priority queue check
``isinstance(item, BusSystemMessage)`` directly instead of
``isinstance(item, SystemFrame)``.

The serializer test that round-tripped DataFrame.name (a non-init
field) is rewritten against a local _MessageWithNonInit(BusDataMessage)
subclass so the serializer's init=False path stays covered.
This commit is contained in:
Aleix Conchillo Flaqué
2026-05-21 09:52:52 -07:00
parent b03247f360
commit d07ba562eb
4 changed files with 37 additions and 30 deletions

View File

@@ -5,6 +5,7 @@
#
import unittest
from dataclasses import dataclass, field
from pydantic import BaseModel
@@ -35,6 +36,11 @@ class _UserInfo(BaseModel):
address: _Address | None = None
@dataclass(kw_only=True)
class _MessageWithNonInit(BusDataMessage):
tag: str = field(init=False, default="default")
class TestJSONMessageSerializer(unittest.TestCase):
def setUp(self):
self.serializer = JSONMessageSerializer()
@@ -232,14 +238,13 @@ class TestJSONMessageSerializer(unittest.TestCase):
def test_non_init_fields_preserved(self):
"""Non-init dataclass fields survive round-trip via setattr."""
msg = BusDataMessage(source="task_a", target="task_b")
# name is a non-init field on DataFrame
msg.name = "custom_name"
msg = _MessageWithNonInit(source="worker_a", target="worker_b")
msg.tag = "custom_tag"
data = self.serializer.serialize(msg)
restored = self.serializer.deserialize(data)
self.assertEqual(restored.name, "custom_name")
self.assertEqual(restored.tag, "custom_tag")
if __name__ == "__main__":