Skip to content

LogicPublisher

faststream.nats.publisher.usecase.LogicPublisher #

LogicPublisher(
    config: NatsPublisherConfig,
    specification: PublisherSpecification[Any, Any],
)

Bases: PublisherUsecase

A class to represent a NATS publisher.

Initialize NATS publisher object.

Source code in faststream/nats/publisher/usecase.py
def __init__(
    self,
    config: "NatsPublisherConfig",
    specification: "PublisherSpecification[Any, Any]",
) -> None:
    """Initialize NATS publisher object."""
    super().__init__(config, specification)

    self._subject = config.subject
    self.stream = config.stream
    self.timeout = config.timeout or 0.5
    self.headers = config.headers or {}
    self.reply_to = config.reply_to

stream instance-attribute #

stream = config.stream

timeout instance-attribute #

timeout = config.timeout or 0.5

headers instance-attribute #

headers = config.headers or {}

reply_to instance-attribute #

reply_to = config.reply_to

subject property #

subject: Address

The subject this Publisher was declared with, and its Broker address.

is_test instance-attribute #

is_test = False

mock property #

mock: MagicMock

The mock recording the endpoint's calls, available under a test broker.

specification instance-attribute #

specification = specification

publish async #

publish(
    message: SendableMessage,
    subject: str = "",
    headers: dict[str, str] | None = None,
    reply_to: str = "",
    correlation_id: str | None = None,
    stream: None = None,
    timeout: float | None = None,
) -> None
publish(
    message: SendableMessage,
    subject: str = "",
    headers: dict[str, str] | None = None,
    reply_to: str = "",
    correlation_id: str | None = None,
    stream: str | None = None,
    timeout: float | None = None,
) -> PubAck
publish(
    message: SendableMessage,
    subject: str = "",
    headers: dict[str, str] | None = None,
    reply_to: str = "",
    correlation_id: str | None = None,
    stream: str | None = None,
    timeout: float | None = None,
) -> Optional[PubAck]

Publish message directly.

PARAMETER DESCRIPTION
message

Message body to send. Can be any encodable object (native python types or pydantic.BaseModel).

TYPE: SendableMessage

subject

NATS subject to send message.

TYPE: str DEFAULT: ''

headers

Message headers to store metainformation. content-type and correlation_id will be set automatically by framework anyway.

TYPE: dict[str, str] | None DEFAULT: None

reply_to

NATS subject name to send response.

TYPE: str DEFAULT: ''

correlation_id

Manual message correlation_id setter. correlation_id is a useful option to trace messages.

TYPE: str | None DEFAULT: None

stream

This option validates that the target subject is in presented stream. Can be omitted without any effect if you doesn't want PubAck frame.

TYPE: str | None DEFAULT: None

timeout

Timeout to send message to NATS.

TYPE: float | None DEFAULT: None

RETURNS DESCRIPTION
Optional[PubAck]

None if you publishes a regular message.

Optional[PubAck]

faststream.nats.PubAck if you publishes a message to stream.

Source code in faststream/nats/publisher/usecase.py
@override
async def publish(
    self,
    message: "SendableMessage",
    subject: str = "",
    headers: dict[str, str] | None = None,
    reply_to: str = "",
    correlation_id: str | None = None,
    stream: str | None = None,
    timeout: float | None = None,
) -> Optional["PubAck"]:
    """Publish message directly.

    Args:
        message:
            Message body to send.
            Can be any encodable object (native python types or `pydantic.BaseModel`).
        subject:
            NATS subject to send message.
        headers:
            Message headers to store metainformation.
            **content-type** and **correlation_id** will be set automatically by framework anyway.
        reply_to:
            NATS subject name to send response.
        correlation_id:
            Manual message **correlation_id** setter.
            **correlation_id** is a useful option to trace messages.
        stream:
            This option validates that the target subject is in presented stream.
            Can be omitted without any effect if you doesn't want PubAck frame.
        timeout:
            Timeout to send message to NATS.

    Returns:
        `None` if you publishes a regular message.
        `faststream.nats.PubAck` if you publishes a message to stream.
    """
    cmd = NatsPublishCommand(
        message,
        subject=subject or self.subject.template,
        headers=self.headers | (headers or {}),
        reply_to=reply_to or self.reply_to,
        correlation_id=correlation_id or self._outer_config.id_generator(),
        stream=stream or getattr(self.stream, "name", None),
        timeout=timeout or self.timeout,
        _publish_type=PublishType.PUBLISH,
    )

    response: PubAck | None
    if cmd.stream:
        response = cast(
            "PubAck",
            await self._basic_publish(
                cmd,
                producer=self._outer_config.js_producer,
                _extra_middlewares=(),
            ),
        )
    else:
        response = await self._basic_publish(
            cmd,
            producer=self._outer_config.producer,
            _extra_middlewares=(),
        )

    return response

request async #

request(
    message: SendableMessage,
    subject: str = "",
    headers: dict[str, str] | None = None,
    correlation_id: str | None = None,
    stream: str | None = None,
    timeout: float = 0.5,
) -> NatsMessage

Make a synchronous request to outer subscriber.

If out subscriber listens subject by stream, you should setup the same stream explicitly. Another way you will reseave confirmation frame as a response.

PARAMETER DESCRIPTION
message

Message body to send. Can be any encodable object (native python types or pydantic.BaseModel).

TYPE: SendableMessage

subject

NATS subject to send message.

TYPE: str DEFAULT: ''

headers

Message headers to store metainformation. content-type and correlation_id will be set automatically by framework anyway.

TYPE: dict[str, str] | None DEFAULT: None

correlation_id

Manual message correlation_id setter. correlation_id is a useful option to trace messages.

TYPE: str | None DEFAULT: None

stream

This allows to make RPC calls over JetStream subjects.

TYPE: str | None DEFAULT: None

timeout

Timeout to send message to NATS.

TYPE: float DEFAULT: 0.5

RETURNS DESCRIPTION
NatsMessage

faststream.nats.message.NatsMessage object as an outer subscriber response.

Source code in faststream/nats/publisher/usecase.py
@override
async def request(
    self,
    message: "SendableMessage",
    subject: str = "",
    headers: dict[str, str] | None = None,
    correlation_id: str | None = None,
    stream: str | None = None,
    timeout: float = 0.5,
) -> "NatsMessage":
    """Make a synchronous request to outer subscriber.

    If out subscriber listens subject by stream, you should setup the same **stream** explicitly.
    Another way you will reseave confirmation frame as a response.

    Args:
        message:
            Message body to send.
            Can be any encodable object (native python types or `pydantic.BaseModel`).
        subject:
            NATS subject to send message.
        headers:
            Message headers to store metainformation.
            **content-type** and **correlation_id** will be set automatically by framework anyway.
        correlation_id:
            Manual message **correlation_id** setter.
            **correlation_id** is a useful option to trace messages.
        stream:
            This allows to make RPC calls over JetStream subjects.
        timeout:
            Timeout to send message to NATS.

    Returns:
        `faststream.nats.message.NatsMessage` object as an outer subscriber response.
    """
    cmd = NatsPublishCommand(
        message=message,
        subject=subject or self.subject.template,
        headers=self.headers | (headers or {}),
        timeout=timeout or self.timeout,
        correlation_id=correlation_id or self._outer_config.id_generator(),
        stream=stream or getattr(self.stream, "name", None),
        _publish_type=PublishType.REQUEST,
    )

    if cmd.stream:
        producer: ProducerProto[Any] = self._outer_config.js_producer
    else:
        producer = self._outer_config.producer

    msg: NatsMessage = await self._basic_request(cmd, producer=producer)
    return msg

assert_called_once_with async #

assert_called_once_with(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None

Assert the endpoint was called once, with the message described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

Source code in faststream/_internal/testing/calls.py
async def assert_called_once_with(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None:
    """Assert the endpoint was called once, with the message described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
    """
    recorder = self._recorder_with_calls()
    recorder.mock.assert_called_once()
    await recorder.assert_last_call(
        ExpectedCall(
            body=body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
        )
    )

assert_called_with async #

assert_called_with(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None

Assert the last message the endpoint saw is the one described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

Source code in faststream/_internal/testing/calls.py
async def assert_called_with(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None:
    """Assert the last message the endpoint saw is the one described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
    """
    recorder = self._recorder_with_calls()
    await recorder.assert_last_call(
        ExpectedCall(
            body=body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
        )
    )

assert_any_call async #

assert_any_call(
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None

Assert one of the messages the endpoint saw is the one described here.

PARAMETER DESCRIPTION
body

The body as a dict, a model or a matcher; it goes through the codec.

TYPE: Any DEFAULT: EMPTY

headers

Headers the message must carry; the rest may carry more.

TYPE: Any DEFAULT: EMPTY

correlation_id

The exact correlation id.

TYPE: Any DEFAULT: EMPTY

reply_to

The exact reply-to destination.

TYPE: Any DEFAULT: EMPTY

content_type

The exact content type.

TYPE: Any DEFAULT: EMPTY

path

The exact path parameters the subject template matched.

TYPE: Any DEFAULT: EMPTY

context

Context paths, as given to Context(), mapped to their values.

TYPE: Mapping[str, Any] DEFAULT: EMPTY

Source code in faststream/_internal/testing/calls.py
async def assert_any_call(
    self,
    body: Any = EMPTY,
    /,
    *,
    headers: Any = EMPTY,
    correlation_id: Any = EMPTY,
    reply_to: Any = EMPTY,
    content_type: Any = EMPTY,
    path: Any = EMPTY,
    context: Mapping[str, Any] = EMPTY,
) -> None:
    """Assert one of the messages the endpoint saw is the one described here.

    Args:
        body: The body as a dict, a model or a matcher; it goes through the codec.
        headers: Headers the message must carry; the rest may carry more.
        correlation_id: The exact correlation id.
        reply_to: The exact reply-to destination.
        content_type: The exact content type.
        path: The exact path parameters the subject template matched.
        context: Context paths, as given to `Context()`, mapped to their values.
    """
    recorder = self._recorder_with_calls()
    await recorder.assert_any_call(
        ExpectedCall(
            body=body,
            headers=headers,
            correlation_id=correlation_id,
            reply_to=reply_to,
            content_type=content_type,
            path=path,
            context=context,
        )
    )

start async #

start() -> None
Source code in faststream/_internal/endpoint/publisher/usecase.py
async def start(self) -> None:
    pass

set_test #

set_test(
    *, recorder: CallRecorder | None = None, with_fake: bool
) -> None

Turn publisher to testing mode, sharing recorder when one is given.

Source code in faststream/_internal/endpoint/publisher/usecase.py
def set_test(
    self,
    *,
    recorder: CallRecorder | None = None,
    with_fake: bool,
) -> None:
    """Turn publisher to testing mode, sharing `recorder` when one is given."""
    self.is_test = True
    if recorder is None:
        self._recorder.reset()
    else:
        self._recorder = recorder
    self._fake_handler = with_fake

reset_test #

reset_test() -> None

Turn off publisher's testing mode.

Source code in faststream/_internal/endpoint/publisher/usecase.py
def reset_test(self) -> None:
    """Turn off publisher's testing mode."""
    self.is_test = False
    self._recorder.reset()
    # A shared recorder goes back to the handler it belongs to
    self._recorder = CallRecorder(self.specification.name, self._outer_config)
    self._fake_handler = False

schema #

schema() -> dict[str, PublisherSpec]
Source code in faststream/_internal/endpoint/publisher/usecase.py
def schema(self) -> dict[str, "PublisherSpec"]:
    return self.specification.get_schema()