# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: bus.proto, command.proto, common.proto, external.proto, info.proto, internal.proto, notify.proto, pipeline.proto, wasm.proto
# plugin: python-betterproto
# This file has been @generated

from dataclasses import dataclass
from typing import (
    TYPE_CHECKING,
    AsyncIterator,
    Dict,
    List,
    Optional,
)

import betterproto
import grpclib
from betterproto.grpc.grpclib_server import ServiceBase

from . import steps


if TYPE_CHECKING:
    import grpclib.server
    from betterproto.grpc.grpclib_client import MetadataLike
    from grpclib.metadata import Deadline


class ResponseCode(betterproto.Enum):
    """Common status codes used in gRPC method responses"""

    RESPONSE_CODE_UNSET = 0
    RESPONSE_CODE_OK = 1
    RESPONSE_CODE_BAD_REQUEST = 2
    RESPONSE_CODE_NOT_FOUND = 3
    RESPONSE_CODE_INTERNAL_SERVER_ERROR = 4
    RESPONSE_CODE_GENERIC_ERROR = 5


class OperationType(betterproto.Enum):
    """Each SDK client is a $service + $component + $operation_type"""

    OPERATION_TYPE_UNSET = 0
    OPERATION_TYPE_CONSUMER = 1
    OPERATION_TYPE_PRODUCER = 2


class PipelineStepCondition(betterproto.Enum):
    """
    A condition defines how the SDK should handle a step response -- should it
    continue executing the pipeline, should it abort, should it notify the
    server? Each step can have multiple conditions.
    """

    PIPELINE_STEP_CONDITION_UNSET = 0
    PIPELINE_STEP_CONDITION_ABORT = 1
    PIPELINE_STEP_CONDITION_NOTIFY = 2


class ClientType(betterproto.Enum):
    CLIENT_TYPE_UNSET = 0
    CLIENT_TYPE_SDK = 1
    CLIENT_TYPE_SHIM = 2


class NotificationType(betterproto.Enum):
    NOTIFICATION_TYPE_UNSET = 0
    NOTIFICATION_TYPE_SLACK = 1
    NOTIFICATION_TYPE_EMAIL = 2
    NOTIFICATION_TYPE_PAGERDUTY = 3


class NotificationEmailType(betterproto.Enum):
    TYPE_UNSET = 0
    TYPE_SMTP = 1
    TYPE_SES = 2


class NotificationPagerDutyUrgency(betterproto.Enum):
    URGENCY_UNSET = 0
    URGENCY_LOW = 1
    URGENCY_HIGH = 2


class WasmExitCode(betterproto.Enum):
    """
    Included in WASM response; SDK is responsible for interpreting the response
    status and how it relates to the step condition. ie. WASM func returns
    WASM_EXIT_CODE_INTERNAL_ERROR lookup ON_ERROR conditions to determine what
    to do next. ie. WASM func returns WASM_EXIT_CODE_SUCCESS lookup ON_MATCH
    conditions to determine what to do next;
    """

    WASM_EXIT_CODE_UNSET = 0
    WASM_EXIT_CODE_SUCCESS = 1
    WASM_EXIT_CODE_FAILURE = 2
    WASM_EXIT_CODE_INTERNAL_ERROR = 3


@dataclass(eq=False, repr=False)
class StandardResponse(betterproto.Message):
    """Common response message for many gRPC methods"""

    id: str = betterproto.string_field(1)
    """Co-relation ID for the request / response"""

    code: "ResponseCode" = betterproto.enum_field(2)
    message: str = betterproto.string_field(3)


@dataclass(eq=False, repr=False)
class Audience(betterproto.Message):
    """Used to indicate who a command is intended for"""

    service_name: str = betterproto.string_field(1)
    """
    Name of the service -- let's include the service name on all calls, we can
    optimize later ~DS
    """

    component_name: str = betterproto.string_field(2)
    """
    Name of the component the SDK is interacting with (ie. kafka-$topic-name)
    """

    operation_type: "OperationType" = betterproto.enum_field(3)
    """Consumer or Producer"""

    operation_name: str = betterproto.string_field(4)
    """Name for the consumer or producer"""


@dataclass(eq=False, repr=False)
class Pipeline(betterproto.Message):
    """
    Pipeline is a structure that holds one or more pipeline steps. This
    structure is intended to be immutable; clients are expected to generate
    WASMRequest's that contain a pipeline step.
    """

    id: str = betterproto.string_field(1)
    """
    ID should NOT be set by external gRPC client on CreatePipelineRequest - it
    will be ignored; it _does_ need to be set on UpdatePipelineRequest.
    """

    name: str = betterproto.string_field(2)
    """Friendly name for the pipeline"""

    steps: List["PipelineStep"] = betterproto.message_field(3)
    """One or more steps to execute"""


@dataclass(eq=False, repr=False)
class PipelineStep(betterproto.Message):
    """A pipeline step is a single step in a pipeline."""

    name: str = betterproto.string_field(1)
    """Friendly name for the step"""

    on_success: List["PipelineStepCondition"] = betterproto.enum_field(2)
    """What should SDK do if step succeeds?"""

    on_failure: List["PipelineStepCondition"] = betterproto.enum_field(3)
    """What should SDK do if step fails?"""

    detective: "steps.DetectiveStep" = betterproto.message_field(1000, group="step")
    transform: "steps.TransformStep" = betterproto.message_field(1001, group="step")
    encode: "steps.EncodeStep" = betterproto.message_field(1002, group="step")
    decode: "steps.DecodeStep" = betterproto.message_field(1003, group="step")
    custom: "steps.CustomStep" = betterproto.message_field(1004, group="step")
    wasm_id: Optional[str] = betterproto.string_field(
        10000, optional=True, group="X_wasm_id"
    )
    """ID is a uuid(sha256(_wasm_bytes)) that is set by snitch-server"""

    wasm_bytes: Optional[bytes] = betterproto.bytes_field(
        10001, optional=True, group="X_wasm_bytes"
    )
    """WASM module bytes (set by snitch-server)"""

    wasm_function: Optional[str] = betterproto.string_field(
        10002, optional=True, group="X_wasm_function"
    )
    """WASM function name to execute (set by snitch-server)"""


@dataclass(eq=False, repr=False)
class LiveInfo(betterproto.Message):
    audiences: List["Audience"] = betterproto.message_field(1)
    """If empty, client has not announced any audiences"""

    client: "ClientInfo" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class PipelineInfo(betterproto.Message):
    audiences: List["Audience"] = betterproto.message_field(1)
    """What audience(s) this pipeline is attached to (none if empty)"""

    pipeline: "Pipeline" = betterproto.message_field(2)
    """Pipeline config"""

    paused: List["Audience"] = betterproto.message_field(3)
    """For what audiences this pipeline is paused (none if empty)"""


@dataclass(eq=False, repr=False)
class ClientInfo(betterproto.Message):
    """
    Most of this is constructed by client SDKs and provided during Register
    call
    """

    client_type: "ClientType" = betterproto.enum_field(1)
    library_name: str = betterproto.string_field(2)
    library_version: str = betterproto.string_field(3)
    language: str = betterproto.string_field(4)
    arch: str = betterproto.string_field(5)
    os: str = betterproto.string_field(6)
    session_id: Optional[str] = betterproto.string_field(
        7, optional=True, group="X_session_id"
    )
    """Filled out by snitch_server on GetAll()"""

    service_name: Optional[str] = betterproto.string_field(
        8, optional=True, group="X_service_name"
    )
    node_name: Optional[str] = betterproto.string_field(
        9, optional=True, group="X_node_name"
    )


@dataclass(eq=False, repr=False)
class NotificationConfig(betterproto.Message):
    id: Optional[str] = betterproto.string_field(1, optional=True, group="_id")
    name: str = betterproto.string_field(2)
    type: "NotificationType" = betterproto.enum_field(3)
    slack: "NotificationSlack" = betterproto.message_field(1000, group="config")
    email: "NotificationEmail" = betterproto.message_field(1001, group="config")
    pagerduty: "NotificationPagerDuty" = betterproto.message_field(1002, group="config")


@dataclass(eq=False, repr=False)
class NotificationSlack(betterproto.Message):
    bot_token: str = betterproto.string_field(1)
    channel: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class NotificationEmail(betterproto.Message):
    type: "NotificationEmailType" = betterproto.enum_field(1)
    recipients: List[str] = betterproto.string_field(2)
    from_address: str = betterproto.string_field(3)
    smtp: "NotificationEmailSmtp" = betterproto.message_field(1000, group="config")
    ses: "NotificationEmailSes" = betterproto.message_field(1001, group="config")


@dataclass(eq=False, repr=False)
class NotificationEmailSmtp(betterproto.Message):
    host: str = betterproto.string_field(1)
    port: int = betterproto.int32_field(2)
    user: str = betterproto.string_field(3)
    password: str = betterproto.string_field(4)
    use_tls: bool = betterproto.bool_field(5)


@dataclass(eq=False, repr=False)
class NotificationEmailSes(betterproto.Message):
    ses_region: str = betterproto.string_field(1)
    ses_access_key_id: str = betterproto.string_field(2)
    ses_secret_access_key: str = betterproto.string_field(3)


@dataclass(eq=False, repr=False)
class NotificationPagerDuty(betterproto.Message):
    token: str = betterproto.string_field(1)
    """Auth token"""

    email: str = betterproto.string_field(2)
    """Must be a valid email for a PagerDuty user"""

    service_id: str = betterproto.string_field(3)
    """Must be a valid PagerDuty service"""

    urgency: "NotificationPagerDutyUrgency" = betterproto.enum_field(4)


@dataclass(eq=False, repr=False)
class GetAllRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetAllResponse(betterproto.Message):
    live: List["LiveInfo"] = betterproto.message_field(1)
    """Clients currently connected to the server"""

    audiences: List["Audience"] = betterproto.message_field(2)
    """All of the audiences that are known to the server"""

    pipelines: Dict[str, "PipelineInfo"] = betterproto.map_field(
        3, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    """
    All of the pipelines known to the server + pipeline <-> audience mappings
    key == pipeline_id; if "Audience" is not filled out - pipeline is not
    attached to any audience.
    """


@dataclass(eq=False, repr=False)
class GetPipelinesRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetPipelinesResponse(betterproto.Message):
    pipelines: List["Pipeline"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class GetPipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class GetPipelineResponse(betterproto.Message):
    pipeline: "Pipeline" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class CreatePipelineRequest(betterproto.Message):
    pipeline: "Pipeline" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class CreatePipelineResponse(betterproto.Message):
    message: str = betterproto.string_field(1)
    pipeline_id: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class UpdatePipelineRequest(betterproto.Message):
    pipeline: "Pipeline" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class DeletePipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class AttachPipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)
    audience: "Audience" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class DetachPipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)
    audience: "Audience" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class PausePipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)
    audience: "Audience" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class ResumePipelineRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)
    audience: "Audience" = betterproto.message_field(2)


@dataclass(eq=False, repr=False)
class CreateNotificationRequest(betterproto.Message):
    """Notifications"""

    notification: "NotificationConfig" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class UpdateNotificationRequest(betterproto.Message):
    notification: "NotificationConfig" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class DeleteNotificationRequest(betterproto.Message):
    notification_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class GetNotificationsRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetNotificationsResponse(betterproto.Message):
    notifications: Dict[str, "NotificationConfig"] = betterproto.map_field(
        1, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    """Key == id of the notification config"""


@dataclass(eq=False, repr=False)
class GetNotificationRequest(betterproto.Message):
    notification_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class GetNotificationResponse(betterproto.Message):
    notification: "NotificationConfig" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class AttachNotificationRequest(betterproto.Message):
    notification_id: str = betterproto.string_field(1)
    pipeline_id: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class DetachNotificationRequest(betterproto.Message):
    notification_id: str = betterproto.string_field(1)
    pipeline_id: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class TestRequest(betterproto.Message):
    input: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class TestResponse(betterproto.Message):
    output: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class Command(betterproto.Message):
    """Command is used by snitch-server for sending commands to SDKs"""

    audience: "Audience" = betterproto.message_field(1)
    """Who is this command intended for?"""

    attach_pipeline: "AttachPipelineCommand" = betterproto.message_field(
        100, group="command"
    )
    detach_pipeline: "DetachPipelineCommand" = betterproto.message_field(
        101, group="command"
    )
    pause_pipeline: "PausePipelineCommand" = betterproto.message_field(
        102, group="command"
    )
    resume_pipeline: "ResumePipelineCommand" = betterproto.message_field(
        103, group="command"
    )
    keep_alive: "KeepAliveCommand" = betterproto.message_field(104, group="command")


@dataclass(eq=False, repr=False)
class AttachPipelineCommand(betterproto.Message):
    pipeline: "Pipeline" = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class DetachPipelineCommand(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class PausePipelineCommand(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class ResumePipelineCommand(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class KeepAliveCommand(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class NewAudienceRequest(betterproto.Message):
    session_id: str = betterproto.string_field(1)
    """The session that is performing this call"""

    audience: "Audience" = betterproto.message_field(2)
    """Newly created audience."""


@dataclass(eq=False, repr=False)
class HeartbeatRequest(betterproto.Message):
    """
    Each consumer and producer should send periodic heartbeats to the server to
    let the server know that they are still active.
    """

    session_id: str = betterproto.string_field(1)
    """Session ID for this instance of the SDK."""


@dataclass(eq=False, repr=False)
class NotifyRequest(betterproto.Message):
    pipeline_id: str = betterproto.string_field(1)
    step_name: str = betterproto.string_field(2)
    audience: "Audience" = betterproto.message_field(3)
    occurred_at_unix_ts_utc: int = betterproto.int64_field(4)


@dataclass(eq=False, repr=False)
class Metrics(betterproto.Message):
    name: str = betterproto.string_field(1)
    labels: Dict[str, str] = betterproto.map_field(
        2, betterproto.TYPE_STRING, betterproto.TYPE_STRING
    )
    value: float = betterproto.double_field(3)


@dataclass(eq=False, repr=False)
class MetricsRequest(betterproto.Message):
    metrics: List["Metrics"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class RegisterRequest(betterproto.Message):
    service_name: str = betterproto.string_field(1)
    """REQUIRED -- Name of the service that is registering."""

    session_id: str = betterproto.string_field(2)
    """
    REQUIRED -- Unique ID for this SDK instance. This should be generated every
    time the SDK is instantiated (oe. every time a NEW registration is
    performed).
    """

    client_info: "ClientInfo" = betterproto.message_field(3)
    """REQUIRED -- Info about the client (lib name, lang, os, arch, etc.)"""

    audiences: List["Audience"] = betterproto.message_field(4)
    """
    OPTIONAL -- if these are defined, these will show up in the UI even if
    there is no active .Process() call from the SDK.
    """

    dry_run: bool = betterproto.bool_field(5)
    """
    OPTIONAL -- If set, we know that any pipelines or steps executed in this
    SDK will NOT modify the input/output data. As in, the SDK will log what it
    _would_ do and always return the original data set.
    """


@dataclass(eq=False, repr=False)
class DeregisterRequest(betterproto.Message):
    """
    Same as RegisterRequest - used for broadcasting a deregistration event
    """

    service_name: str = betterproto.string_field(1)
    session_id: str = betterproto.string_field(2)


@dataclass(eq=False, repr=False)
class GetAttachCommandsByServiceRequest(betterproto.Message):
    service_name: str = betterproto.string_field(1)


@dataclass(eq=False, repr=False)
class GetAttachCommandsByServiceResponse(betterproto.Message):
    commands: List["Command"] = betterproto.message_field(1)


@dataclass(eq=False, repr=False)
class BusEvent(betterproto.Message):
    """
    Type used by `snitch-server` for broadcasting events to other snitch nodes
    """

    source: str = betterproto.string_field(1)
    register_request: "RegisterRequest" = betterproto.message_field(100, group="event")
    deregister_request: "DeregisterRequest" = betterproto.message_field(
        101, group="event"
    )
    create_pipeline_request: "CreatePipelineRequest" = betterproto.message_field(
        102, group="event"
    )
    delete_pipeline_request: "DeletePipelineRequest" = betterproto.message_field(
        103, group="event"
    )
    update_pipeline_request: "UpdatePipelineRequest" = betterproto.message_field(
        104, group="event"
    )
    attach_pipeline_request: "AttachPipelineRequest" = betterproto.message_field(
        105, group="event"
    )
    detach_pipeline_request: "DetachPipelineRequest" = betterproto.message_field(
        106, group="event"
    )
    pause_pipeline_request: "PausePipelineRequest" = betterproto.message_field(
        107, group="event"
    )
    resume_pipeline_request: "ResumePipelineRequest" = betterproto.message_field(
        108, group="event"
    )
    metrics_request: "MetricsRequest" = betterproto.message_field(109, group="event")
    metadata: Dict[str, str] = betterproto.map_field(
        1000, betterproto.TYPE_STRING, betterproto.TYPE_STRING
    )
    """
    All gRPC metadata is stored in ctx; when request goes outside of gRPC
    bounds, we will translate ctx metadata into this field. Example: 1. Request
    comes into snitch-server via external gRPC to set new pipeline 2. snitch-
    server has to send SetPipeline cmd to SDK via gRPC - it passes    on
    original metadata in request. 3. snitch-server has to broadcast SetPipeline
    cmd to other services via bus 4. Since this is not a gRPC call, snitch-
    server translates ctx metadata to    this field and includes it in the bus
    event.
    """


@dataclass(eq=False, repr=False)
class WasmRequest(betterproto.Message):
    """SDK generates a WASM request and passes this to the WASM func"""

    step: "PipelineStep" = betterproto.message_field(1)
    input: bytes = betterproto.bytes_field(2)


@dataclass(eq=False, repr=False)
class WasmResponse(betterproto.Message):
    """Returned by all WASM functions"""

    output: bytes = betterproto.bytes_field(1)
    exit_code: "WasmExitCode" = betterproto.enum_field(2)
    exit_msg: str = betterproto.string_field(3)


class ExternalStub(betterproto.ServiceStub):
    async def get_all(
        self,
        get_all_request: "GetAllRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetAllResponse":
        return await self._unary_unary(
            "/protos.External/GetAll",
            get_all_request,
            GetAllResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_pipelines(
        self,
        get_pipelines_request: "GetPipelinesRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetPipelinesResponse":
        return await self._unary_unary(
            "/protos.External/GetPipelines",
            get_pipelines_request,
            GetPipelinesResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_pipeline(
        self,
        get_pipeline_request: "GetPipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetPipelineResponse":
        return await self._unary_unary(
            "/protos.External/GetPipeline",
            get_pipeline_request,
            GetPipelineResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def create_pipeline(
        self,
        create_pipeline_request: "CreatePipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "CreatePipelineResponse":
        return await self._unary_unary(
            "/protos.External/CreatePipeline",
            create_pipeline_request,
            CreatePipelineResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def update_pipeline(
        self,
        update_pipeline_request: "UpdatePipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/UpdatePipeline",
            update_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def delete_pipeline(
        self,
        delete_pipeline_request: "DeletePipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/DeletePipeline",
            delete_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def attach_pipeline(
        self,
        attach_pipeline_request: "AttachPipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/AttachPipeline",
            attach_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def detach_pipeline(
        self,
        detach_pipeline_request: "DetachPipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/DetachPipeline",
            detach_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def pause_pipeline(
        self,
        pause_pipeline_request: "PausePipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/PausePipeline",
            pause_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def resume_pipeline(
        self,
        resume_pipeline_request: "ResumePipelineRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/ResumePipeline",
            resume_pipeline_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def create_notification(
        self,
        create_notification_request: "CreateNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/CreateNotification",
            create_notification_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def update_notification(
        self,
        update_notification_request: "UpdateNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/UpdateNotification",
            update_notification_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def delete_notification(
        self,
        delete_notification_request: "DeleteNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/DeleteNotification",
            delete_notification_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_notifications(
        self,
        get_notifications_request: "GetNotificationsRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetNotificationsResponse":
        return await self._unary_unary(
            "/protos.External/GetNotifications",
            get_notifications_request,
            GetNotificationsResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_notification(
        self,
        get_notification_request: "GetNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetNotificationResponse":
        return await self._unary_unary(
            "/protos.External/GetNotification",
            get_notification_request,
            GetNotificationResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def attach_notification(
        self,
        attach_notification_request: "AttachNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/AttachNotification",
            attach_notification_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def detach_notification(
        self,
        detach_notification_request: "DetachNotificationRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.External/DetachNotification",
            detach_notification_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def test(
        self,
        test_request: "TestRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "TestResponse":
        return await self._unary_unary(
            "/protos.External/Test",
            test_request,
            TestResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class InternalStub(betterproto.ServiceStub):
    async def register(
        self,
        register_request: "RegisterRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> AsyncIterator["Command"]:
        async for response in self._unary_stream(
            "/protos.Internal/Register",
            register_request,
            Command,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        ):
            yield response

    async def new_audience(
        self,
        new_audience_request: "NewAudienceRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.Internal/NewAudience",
            new_audience_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def heartbeat(
        self,
        heartbeat_request: "HeartbeatRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.Internal/Heartbeat",
            heartbeat_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def notify(
        self,
        notify_request: "NotifyRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.Internal/Notify",
            notify_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def metrics(
        self,
        metrics_request: "MetricsRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "StandardResponse":
        return await self._unary_unary(
            "/protos.Internal/Metrics",
            metrics_request,
            StandardResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )

    async def get_attach_commands_by_service(
        self,
        get_attach_commands_by_service_request: "GetAttachCommandsByServiceRequest",
        *,
        timeout: Optional[float] = None,
        deadline: Optional["Deadline"] = None,
        metadata: Optional["MetadataLike"] = None
    ) -> "GetAttachCommandsByServiceResponse":
        return await self._unary_unary(
            "/protos.Internal/GetAttachCommandsByService",
            get_attach_commands_by_service_request,
            GetAttachCommandsByServiceResponse,
            timeout=timeout,
            deadline=deadline,
            metadata=metadata,
        )


class ExternalBase(ServiceBase):
    async def get_all(self, get_all_request: "GetAllRequest") -> "GetAllResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_pipelines(
        self, get_pipelines_request: "GetPipelinesRequest"
    ) -> "GetPipelinesResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_pipeline(
        self, get_pipeline_request: "GetPipelineRequest"
    ) -> "GetPipelineResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def create_pipeline(
        self, create_pipeline_request: "CreatePipelineRequest"
    ) -> "CreatePipelineResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def update_pipeline(
        self, update_pipeline_request: "UpdatePipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def delete_pipeline(
        self, delete_pipeline_request: "DeletePipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def attach_pipeline(
        self, attach_pipeline_request: "AttachPipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def detach_pipeline(
        self, detach_pipeline_request: "DetachPipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def pause_pipeline(
        self, pause_pipeline_request: "PausePipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def resume_pipeline(
        self, resume_pipeline_request: "ResumePipelineRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def create_notification(
        self, create_notification_request: "CreateNotificationRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def update_notification(
        self, update_notification_request: "UpdateNotificationRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def delete_notification(
        self, delete_notification_request: "DeleteNotificationRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_notifications(
        self, get_notifications_request: "GetNotificationsRequest"
    ) -> "GetNotificationsResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_notification(
        self, get_notification_request: "GetNotificationRequest"
    ) -> "GetNotificationResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def attach_notification(
        self, attach_notification_request: "AttachNotificationRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def detach_notification(
        self, detach_notification_request: "DetachNotificationRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def test(self, test_request: "TestRequest") -> "TestResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_all(
        self, stream: "grpclib.server.Stream[GetAllRequest, GetAllResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_all(request)
        await stream.send_message(response)

    async def __rpc_get_pipelines(
        self, stream: "grpclib.server.Stream[GetPipelinesRequest, GetPipelinesResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_pipelines(request)
        await stream.send_message(response)

    async def __rpc_get_pipeline(
        self, stream: "grpclib.server.Stream[GetPipelineRequest, GetPipelineResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_pipeline(request)
        await stream.send_message(response)

    async def __rpc_create_pipeline(
        self,
        stream: "grpclib.server.Stream[CreatePipelineRequest, CreatePipelineResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.create_pipeline(request)
        await stream.send_message(response)

    async def __rpc_update_pipeline(
        self, stream: "grpclib.server.Stream[UpdatePipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.update_pipeline(request)
        await stream.send_message(response)

    async def __rpc_delete_pipeline(
        self, stream: "grpclib.server.Stream[DeletePipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.delete_pipeline(request)
        await stream.send_message(response)

    async def __rpc_attach_pipeline(
        self, stream: "grpclib.server.Stream[AttachPipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.attach_pipeline(request)
        await stream.send_message(response)

    async def __rpc_detach_pipeline(
        self, stream: "grpclib.server.Stream[DetachPipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.detach_pipeline(request)
        await stream.send_message(response)

    async def __rpc_pause_pipeline(
        self, stream: "grpclib.server.Stream[PausePipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.pause_pipeline(request)
        await stream.send_message(response)

    async def __rpc_resume_pipeline(
        self, stream: "grpclib.server.Stream[ResumePipelineRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.resume_pipeline(request)
        await stream.send_message(response)

    async def __rpc_create_notification(
        self,
        stream: "grpclib.server.Stream[CreateNotificationRequest, StandardResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.create_notification(request)
        await stream.send_message(response)

    async def __rpc_update_notification(
        self,
        stream: "grpclib.server.Stream[UpdateNotificationRequest, StandardResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.update_notification(request)
        await stream.send_message(response)

    async def __rpc_delete_notification(
        self,
        stream: "grpclib.server.Stream[DeleteNotificationRequest, StandardResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.delete_notification(request)
        await stream.send_message(response)

    async def __rpc_get_notifications(
        self,
        stream: "grpclib.server.Stream[GetNotificationsRequest, GetNotificationsResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_notifications(request)
        await stream.send_message(response)

    async def __rpc_get_notification(
        self,
        stream: "grpclib.server.Stream[GetNotificationRequest, GetNotificationResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_notification(request)
        await stream.send_message(response)

    async def __rpc_attach_notification(
        self,
        stream: "grpclib.server.Stream[AttachNotificationRequest, StandardResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.attach_notification(request)
        await stream.send_message(response)

    async def __rpc_detach_notification(
        self,
        stream: "grpclib.server.Stream[DetachNotificationRequest, StandardResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.detach_notification(request)
        await stream.send_message(response)

    async def __rpc_test(
        self, stream: "grpclib.server.Stream[TestRequest, TestResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.test(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/protos.External/GetAll": grpclib.const.Handler(
                self.__rpc_get_all,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetAllRequest,
                GetAllResponse,
            ),
            "/protos.External/GetPipelines": grpclib.const.Handler(
                self.__rpc_get_pipelines,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPipelinesRequest,
                GetPipelinesResponse,
            ),
            "/protos.External/GetPipeline": grpclib.const.Handler(
                self.__rpc_get_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetPipelineRequest,
                GetPipelineResponse,
            ),
            "/protos.External/CreatePipeline": grpclib.const.Handler(
                self.__rpc_create_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                CreatePipelineRequest,
                CreatePipelineResponse,
            ),
            "/protos.External/UpdatePipeline": grpclib.const.Handler(
                self.__rpc_update_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                UpdatePipelineRequest,
                StandardResponse,
            ),
            "/protos.External/DeletePipeline": grpclib.const.Handler(
                self.__rpc_delete_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                DeletePipelineRequest,
                StandardResponse,
            ),
            "/protos.External/AttachPipeline": grpclib.const.Handler(
                self.__rpc_attach_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                AttachPipelineRequest,
                StandardResponse,
            ),
            "/protos.External/DetachPipeline": grpclib.const.Handler(
                self.__rpc_detach_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                DetachPipelineRequest,
                StandardResponse,
            ),
            "/protos.External/PausePipeline": grpclib.const.Handler(
                self.__rpc_pause_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                PausePipelineRequest,
                StandardResponse,
            ),
            "/protos.External/ResumePipeline": grpclib.const.Handler(
                self.__rpc_resume_pipeline,
                grpclib.const.Cardinality.UNARY_UNARY,
                ResumePipelineRequest,
                StandardResponse,
            ),
            "/protos.External/CreateNotification": grpclib.const.Handler(
                self.__rpc_create_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                CreateNotificationRequest,
                StandardResponse,
            ),
            "/protos.External/UpdateNotification": grpclib.const.Handler(
                self.__rpc_update_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                UpdateNotificationRequest,
                StandardResponse,
            ),
            "/protos.External/DeleteNotification": grpclib.const.Handler(
                self.__rpc_delete_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                DeleteNotificationRequest,
                StandardResponse,
            ),
            "/protos.External/GetNotifications": grpclib.const.Handler(
                self.__rpc_get_notifications,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetNotificationsRequest,
                GetNotificationsResponse,
            ),
            "/protos.External/GetNotification": grpclib.const.Handler(
                self.__rpc_get_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetNotificationRequest,
                GetNotificationResponse,
            ),
            "/protos.External/AttachNotification": grpclib.const.Handler(
                self.__rpc_attach_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                AttachNotificationRequest,
                StandardResponse,
            ),
            "/protos.External/DetachNotification": grpclib.const.Handler(
                self.__rpc_detach_notification,
                grpclib.const.Cardinality.UNARY_UNARY,
                DetachNotificationRequest,
                StandardResponse,
            ),
            "/protos.External/Test": grpclib.const.Handler(
                self.__rpc_test,
                grpclib.const.Cardinality.UNARY_UNARY,
                TestRequest,
                TestResponse,
            ),
        }


class InternalBase(ServiceBase):
    async def register(
        self, register_request: "RegisterRequest"
    ) -> AsyncIterator["Command"]:
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
        yield Command()

    async def new_audience(
        self, new_audience_request: "NewAudienceRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def heartbeat(
        self, heartbeat_request: "HeartbeatRequest"
    ) -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def notify(self, notify_request: "NotifyRequest") -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def metrics(self, metrics_request: "MetricsRequest") -> "StandardResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def get_attach_commands_by_service(
        self,
        get_attach_commands_by_service_request: "GetAttachCommandsByServiceRequest",
    ) -> "GetAttachCommandsByServiceResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_register(
        self, stream: "grpclib.server.Stream[RegisterRequest, Command]"
    ) -> None:
        request = await stream.recv_message()
        await self._call_rpc_handler_server_stream(
            self.register,
            stream,
            request,
        )

    async def __rpc_new_audience(
        self, stream: "grpclib.server.Stream[NewAudienceRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.new_audience(request)
        await stream.send_message(response)

    async def __rpc_heartbeat(
        self, stream: "grpclib.server.Stream[HeartbeatRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.heartbeat(request)
        await stream.send_message(response)

    async def __rpc_notify(
        self, stream: "grpclib.server.Stream[NotifyRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.notify(request)
        await stream.send_message(response)

    async def __rpc_metrics(
        self, stream: "grpclib.server.Stream[MetricsRequest, StandardResponse]"
    ) -> None:
        request = await stream.recv_message()
        response = await self.metrics(request)
        await stream.send_message(response)

    async def __rpc_get_attach_commands_by_service(
        self,
        stream: "grpclib.server.Stream[GetAttachCommandsByServiceRequest, GetAttachCommandsByServiceResponse]",
    ) -> None:
        request = await stream.recv_message()
        response = await self.get_attach_commands_by_service(request)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/protos.Internal/Register": grpclib.const.Handler(
                self.__rpc_register,
                grpclib.const.Cardinality.UNARY_STREAM,
                RegisterRequest,
                Command,
            ),
            "/protos.Internal/NewAudience": grpclib.const.Handler(
                self.__rpc_new_audience,
                grpclib.const.Cardinality.UNARY_UNARY,
                NewAudienceRequest,
                StandardResponse,
            ),
            "/protos.Internal/Heartbeat": grpclib.const.Handler(
                self.__rpc_heartbeat,
                grpclib.const.Cardinality.UNARY_UNARY,
                HeartbeatRequest,
                StandardResponse,
            ),
            "/protos.Internal/Notify": grpclib.const.Handler(
                self.__rpc_notify,
                grpclib.const.Cardinality.UNARY_UNARY,
                NotifyRequest,
                StandardResponse,
            ),
            "/protos.Internal/Metrics": grpclib.const.Handler(
                self.__rpc_metrics,
                grpclib.const.Cardinality.UNARY_UNARY,
                MetricsRequest,
                StandardResponse,
            ),
            "/protos.Internal/GetAttachCommandsByService": grpclib.const.Handler(
                self.__rpc_get_attach_commands_by_service,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetAttachCommandsByServiceRequest,
                GetAttachCommandsByServiceResponse,
            ),
        }
