diff --git a/faststream_outbox/broker.py b/faststream_outbox/broker.py index 64d7042..d2e76e3 100644 --- a/faststream_outbox/broker.py +++ b/faststream_outbox/broker.py @@ -94,6 +94,13 @@ async def after_processed( class OutboxParamsStorage(DefaultLoggerStorage): + def __init__(self) -> None: + super().__init__() + self._max_queue_len = 7 + + def register_subscriber(self, params: dict[str, typing.Any]) -> None: + self._max_queue_len = max(self._max_queue_len, len(params.get("queue", ""))) + def get_logger(self, *, context: "ContextRepo") -> LoggerProto: if logger := self._get_logger_ref(): return logger @@ -101,7 +108,7 @@ def get_logger(self, *, context: "ContextRepo") -> LoggerProto: name="outbox", default_context={"queue": "", "message_id": ""}, message_id_ln=-1, - fmt="%(asctime)s %(levelname)-8s - %(queue)-7s | %(message_id)s - %(message)s", + fmt=f"%(asctime)s %(levelname)-8s - %(queue)-{self._max_queue_len}s | %(message_id)s - %(message)s", context=context, log_level=self.logger_log_level, ) diff --git a/tests/test_adr_citations.py b/tests/test_adr_citations.py index 760f6f1..7f7706c 100644 --- a/tests/test_adr_citations.py +++ b/tests/test_adr_citations.py @@ -7,7 +7,7 @@ _REPO_ROOT: typing.Final = pathlib.Path(__file__).resolve().parent.parent _ADR_DIR: typing.Final = "docs/adr/" -_CITATION: typing.Final = re.compile(r"docs/adr/\d{4}-[a-z0-9-]+\.md") +_CITATION: typing.Final = re.compile(r"docs/adr/\d{4}(?:-[a-z0-9-]+\.md)?") _UNWALKED_DIR: typing.Final = "node_modules" @@ -45,6 +45,8 @@ def test_every_adr_path_cited_from_python_resolves() -> None: offline link gate reads Markdown only, so a path in a docstring, a comment or a guard message is otherwise checked by nothing, and an `INVARIANT:` docstring that names its ADR silently loses the rationale the test depends on. A user who trips a guard is handed a link to follow. + A bare `docs/adr/NNNN` is reported as well: it names no file, so it would survive the same + rename or drop unnoticed and point at whatever record holds that number next. """ unresolved = unresolved_citations(_REPO_ROOT) @@ -64,6 +66,18 @@ def test_a_citation_of_a_missing_adr_is_reported_with_its_citing_file(tmp_path: assert unresolved_citations(tmp_path) == [("pkg/mod.py", f"{_ADR_DIR}9999-missing.md")] +def test_a_short_form_citation_is_reported_even_when_the_adr_exists(tmp_path: pathlib.Path) -> None: + """`docs/adr/NNNN` with no slug names nothing on disk, so a rename or a drop never breaks it.""" + (tmp_path / _ADR_DIR).mkdir(parents=True) + (tmp_path / _ADR_DIR / "0002-kept.md").write_text("# kept\n", encoding="utf-8") + (tmp_path / "pkg").mkdir() + (tmp_path / "pkg" / "mod.py").write_text( + f'"""Argued in {_ADR_DIR}0002 and {_ADR_DIR}0002-kept.md."""\n', encoding="utf-8" + ) + + assert unresolved_citations(tmp_path) == [("pkg/mod.py", f"{_ADR_DIR}0002")] + + def test_a_citation_split_across_adjacent_string_literals_is_found(tmp_path: pathlib.Path) -> None: """Python joins adjacent literals at parse time, which is what the `nack` guard message relies on.""" (tmp_path / "guard.py").write_text( diff --git a/tests/test_unit.py b/tests/test_unit.py index 7c02d94..aa3f719 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -1608,6 +1608,16 @@ def test_outbox_params_storage_caches_logger() -> None: assert a is b +def test_outbox_params_storage_widens_the_queue_column_for_registered_subscribers() -> None: + logging.getLogger("faststream.access.outbox").handlers.clear() + storage = OutboxParamsStorage() + storage.register_subscriber({"queue": "orders-priority"}) + storage.get_logger(context=MagicMock()) + formatter = logging.getLogger("faststream.access.outbox").handlers[0].formatter + assert formatter is not None + assert "%(queue)-15s" in (formatter._fmt or "") # noqa: SLF001 + + # --- configs ---