Beispiel #1
0
class AppT(ServiceT):
    """Abstract type for the Faust application.

    See Also:
        :class:`faust.App`.
    """

    Settings: ClassVar[Type[_Settings]]

    BootStrategy: ClassVar[Type[BootStrategyT]]
    boot_strategy: BootStrategyT

    #: Set to true when the app is finalized (can read configuration).
    finalized: bool = False

    #: Set to true when the app has read configuration.
    configured: bool = False

    #: Set to true if the worker is currently rebalancing.
    rebalancing: bool = False
    rebalancing_count: int = 0
    #: Set to true when the worker is in recovery
    in_recovery: bool = False

    consumer_generation_id: int = 0

    #: Set to true if the assignment is empty
    # This flag is set by App._on_partitions_assigned
    unassigned: bool = False

    #: Set to true when app is executing within a worker instance.
    # This flag is set in faust/worker.py
    in_worker: bool = False

    on_configured: SyncSignal[_Settings] = SyncSignal()
    on_before_configured: SyncSignal = SyncSignal()
    on_after_configured: SyncSignal = SyncSignal()
    on_partitions_assigned: Signal[Set[TP]] = Signal()
    on_partitions_revoked: Signal[Set[TP]] = Signal()
    on_rebalance_complete: Signal = Signal()
    on_before_shutdown: Signal = Signal()
    on_worker_init: SyncSignal = SyncSignal()
    on_produce_message: SyncSignal = SyncSignal()

    client_only: bool
    producer_only: bool

    agents: AgentManagerT
    sensors: SensorDelegateT

    fixups: MutableSequence[FixupT]

    tracer: Optional[TracerT] = None

    #: Original id argument + kwargs passed to App.__init__
    _default_options: Tuple[str, Mapping[str, Any]]

    @abc.abstractmethod
    def __init__(self,
                 id: str,
                 *,
                 monitor: _Monitor,
                 config_source: Any = None,
                 **options: Any) -> None:
        self.on_startup_finished: Optional[Callable] = None

    @abc.abstractmethod
    def config_from_object(self,
                           obj: Any,
                           *,
                           silent: bool = False,
                           force: bool = False) -> None:
        ...

    @abc.abstractmethod
    def finalize(self) -> None:
        ...

    @abc.abstractmethod
    def main(self) -> NoReturn:
        ...

    @abc.abstractmethod
    def worker_init(self) -> None:
        ...

    @abc.abstractmethod
    def worker_init_post_autodiscover(self) -> None:
        ...

    @abc.abstractmethod
    def discover(
            self,
            *extra_modules: str,
            categories: Iterable[str] = ("a", "b", "c"),
            ignore: Iterable[Any] = ("foo", "bar"),
    ) -> None:
        ...

    @abc.abstractmethod
    def topic(
        self,
        *topics: str,
        pattern: Union[str, Pattern] = None,
        schema: Optional[_SchemaT] = None,
        key_type: _ModelArg = None,
        value_type: _ModelArg = None,
        key_serializer: CodecArg = None,
        value_serializer: CodecArg = None,
        partitions: Optional[int] = None,
        retention: Optional[Seconds] = None,
        compacting: Optional[bool] = None,
        deleting: Optional[bool] = None,
        replicas: Optional[int] = None,
        acks: bool = True,
        internal: bool = False,
        config: Optional[Mapping[str, Any]] = None,
        maxsize: Optional[int] = None,
        allow_empty: bool = False,
        has_prefix: bool = False,
        loop: Optional[asyncio.AbstractEventLoop] = None,
    ) -> TopicT:
        ...

    @abc.abstractmethod
    def channel(
        self,
        *,
        schema: Optional[_SchemaT] = None,
        key_type: _ModelArg = None,
        value_type: _ModelArg = None,
        maxsize: Optional[int] = None,
        loop: Optional[asyncio.AbstractEventLoop] = None,
    ) -> ChannelT:
        ...

    @abc.abstractmethod
    def agent(
        self,
        channel: Union[str, ChannelT[_T]] = None,
        *,
        name: Optional[str] = None,
        concurrency: int = 1,
        supervisor_strategy: Type[SupervisorStrategyT] = None,
        sink: Iterable[SinkT] = None,
        isolated_partitions: bool = False,
        use_reply_headers: bool = True,
        **kwargs: Any,
    ) -> Callable[[AgentFun[_T]], AgentT[_T]]:
        ...

    @abc.abstractmethod
    @no_type_check
    def task(self,
             fun: TaskArg,
             *,
             on_leader: bool = False,
             traced: bool = True) -> Callable:
        ...

    @abc.abstractmethod
    def timer(
        self,
        interval: Seconds,
        on_leader: bool = False,
        traced: bool = True,
        name: Optional[str] = None,
        max_drift_correction: float = 0.1,
    ) -> Callable:
        ...

    @abc.abstractmethod
    def crontab(
        self,
        cron_format: str,
        *,
        timezone: tzinfo = None,
        on_leader: bool = False,
        traced: bool = True,
    ) -> Callable:
        ...

    @abc.abstractmethod
    def service(self, cls: Type[ServiceT]) -> Type[ServiceT]:
        ...

    @abc.abstractmethod
    def stream(self,
               channel: AsyncIterable,
               beacon: Optional[NodeT] = None,
               **kwargs: Any) -> StreamT:
        ...

    @abc.abstractmethod
    def Table(
        self,
        name: str,
        *,
        default: Callable[[], Any] = None,
        window: Optional[WindowT] = None,
        partitions: Optional[int] = None,
        help: Optional[str] = None,
        **kwargs: Any,
    ) -> TableT:
        ...

    @abc.abstractmethod
    def GlobalTable(
        self,
        name: str,
        *,
        default: Callable[[], Any] = None,
        window: Optional[WindowT] = None,
        partitions: Optional[int] = None,
        help: Optional[str] = None,
        **kwargs: Any,
    ) -> TableT:
        ...

    @abc.abstractmethod
    def SetTable(
        self,
        name: str,
        *,
        window: Optional[WindowT] = None,
        partitions: Optional[int] = None,
        start_manager: bool = False,
        help: Optional[str] = None,
        **kwargs: Any,
    ) -> TableT:
        ...

    @abc.abstractmethod
    def SetGlobalTable(
        self,
        name: str,
        *,
        window: Optional[WindowT] = None,
        partitions: Optional[int] = None,
        start_manager: bool = False,
        help: Optional[str] = None,
        **kwargs: Any,
    ) -> TableT:
        ...

    @abc.abstractmethod
    def page(
        self,
        path: str,
        *,
        base: Type[View] = View,
        cors_options: Mapping[str, ResourceOptions] = None,
        name: Optional[str] = None,
    ) -> Callable[[PageArg], Type[View]]:
        ...

    @abc.abstractmethod
    def table_route(
        self,
        table: CollectionT,
        shard_param: Optional[str] = None,
        *,
        query_param: Optional[str] = None,
        match_info: Optional[str] = None,
        exact_key: Optional[str] = None,
    ) -> ViewDecorator:
        ...

    @abc.abstractmethod
    def command(self,
                *options: Any,
                base: Type[_AppCommand] = None,
                **kwargs: Any) -> Callable[[Callable], Type[_AppCommand]]:
        ...

    @abc.abstractmethod
    def create_event(self, key: K, value: V, headers: HeadersArg,
                     message: Message) -> _EventT:
        ...

    @abc.abstractmethod
    async def start_client(self) -> None:
        ...

    @abc.abstractmethod
    async def maybe_start_client(self) -> None:
        ...

    @abc.abstractmethod
    def trace(self,
              name: str,
              trace_enabled: bool = True,
              **extra_context: Any) -> ContextManager:
        ...

    @abc.abstractmethod
    async def send(
        self,
        channel: Union[ChannelT, str],
        key: K = None,
        value: V = None,
        partition: Optional[int] = None,
        timestamp: Optional[float] = None,
        headers: HeadersArg = None,
        schema: Optional[_SchemaT] = None,
        key_serializer: CodecArg = None,
        value_serializer: CodecArg = None,
        callback: Optional[MessageSentCallback] = None,
    ) -> Awaitable[RecordMetadata]:
        ...

    @abc.abstractmethod
    def LiveCheck(self, **kwargs: Any) -> _LiveCheck:
        ...

    @stampede
    @abc.abstractmethod
    async def maybe_start_producer(self) -> ProducerT:
        ...

    @abc.abstractmethod
    def is_leader(self) -> bool:
        ...

    @abc.abstractmethod
    def FlowControlQueue(
        self,
        maxsize: Optional[int] = None,
        *,
        clear_on_resume: bool = False,
    ) -> ThrowableQueue:
        ...

    @abc.abstractmethod
    def Worker(self, **kwargs: Any) -> _Worker:
        ...

    @abc.abstractmethod
    def on_webserver_init(self, web: Web) -> None:
        ...

    @abc.abstractmethod
    def on_rebalance_start(self) -> None:
        ...

    @abc.abstractmethod
    def on_rebalance_return(self) -> None:
        ...

    @abc.abstractmethod
    def on_rebalance_end(self) -> None:
        ...

    @property
    def conf(self) -> _Settings:
        ...

    @conf.setter
    def conf(self, settings: _Settings) -> None:
        ...

    @property
    @abc.abstractmethod
    def transport(self) -> TransportT:
        ...

    @transport.setter
    def transport(self, transport: TransportT) -> None:
        ...

    @property
    @abc.abstractmethod
    def producer_transport(self) -> TransportT:
        ...

    @producer_transport.setter
    def producer_transport(self, transport: TransportT) -> None:
        ...

    @property
    @abc.abstractmethod
    def cache(self) -> CacheBackendT:
        ...

    @cache.setter
    def cache(self, cache: CacheBackendT) -> None:
        ...

    @property
    @abc.abstractmethod
    def producer(self) -> ProducerT:
        ...

    @property
    @abc.abstractmethod
    def consumer(self) -> ConsumerT:
        ...

    @cached_property
    @abc.abstractmethod
    def tables(self) -> TableManagerT:
        ...

    @cached_property
    @abc.abstractmethod
    def topics(self) -> ConductorT:
        ...

    @property
    @abc.abstractmethod
    def monitor(self) -> _Monitor:
        ...

    @monitor.setter
    def monitor(self, value: _Monitor) -> None:
        ...

    @cached_property
    @abc.abstractmethod
    def flow_control(self) -> FlowControlEvent:
        return FlowControlEvent(loop=self.loop)

    @property
    @abc.abstractmethod
    def http_client(self) -> HttpClientT:
        ...

    @http_client.setter
    def http_client(self, client: HttpClientT) -> None:
        ...

    @cached_property
    @abc.abstractmethod
    def assignor(self) -> PartitionAssignorT:
        ...

    @cached_property
    @abc.abstractmethod
    def router(self) -> RouterT:
        ...

    @cached_property
    @abc.abstractmethod
    def serializers(self) -> RegistryT:
        ...

    @cached_property
    @abc.abstractmethod
    def web(self) -> Web:
        ...

    @cached_property
    @abc.abstractmethod
    def in_transaction(self) -> bool:
        ...

    @abc.abstractmethod
    def _span_add_default_tags(self, span: opentracing.Span) -> None:
        ...

    @abc.abstractmethod
    def _start_span_from_rebalancing(self, name: str) -> opentracing.Span:
        ...
Beispiel #2
0
class AppT(ServiceT):
    """Abstract type for the Faust application.

    See Also:
        :class:`faust.App`.
    """

    BootStrategy: ClassVar[Type[BootStrategyT]]
    boot_strategy: BootStrategyT

    #: Set to true when the app is finalized (can read configuration).
    finalized: bool = False

    #: Set to true when the app has read configuration.
    configured: bool = False

    #: Set to true if the worker is currently rebalancing.
    rebalancing: bool = False

    #: Set to true if the assignment is empty
    # This flag is set by App._on_partitions_assigned
    unassigned: bool = False

    on_configured: SyncSignal[Settings] = SyncSignal()
    on_before_configured: SyncSignal = SyncSignal()
    on_after_configured: SyncSignal = SyncSignal()
    on_partitions_assigned: Signal[Set[TP]] = Signal()
    on_partitions_revoked: Signal[Set[TP]] = Signal()
    on_rebalance_complete: Signal = Signal()
    on_before_shutdown: Signal = Signal()
    on_worker_init: SyncSignal = SyncSignal()

    client_only: bool

    agents: AgentManagerT
    sensors: SensorDelegateT

    fixups: MutableSequence[FixupT]

    @abc.abstractmethod
    def __init__(self,
                 id: str,
                 *,
                 monitor: Monitor,
                 config_source: Any = None,
                 **options: Any) -> None:
        self.on_startup_finished: Optional[Callable] = None

    @abc.abstractmethod
    def config_from_object(self,
                           obj: Any,
                           *,
                           silent: bool = False,
                           force: bool = False) -> None:
        ...

    @abc.abstractmethod
    def finalize(self) -> None:
        ...

    @abc.abstractmethod
    def main(self) -> None:
        ...

    @abc.abstractmethod
    def worker_init(self) -> None:
        ...

    @abc.abstractmethod
    def discover(self,
                 *extra_modules: str,
                 categories: Iterable[str] = ('a', 'b', 'c'),
                 ignore: Iterable[str] = ('foo', 'bar')) -> None:
        ...

    @abc.abstractmethod
    def topic(self,
              *topics: str,
              pattern: Union[str, Pattern] = None,
              key_type: ModelArg = None,
              value_type: ModelArg = None,
              key_serializer: CodecArg = None,
              value_serializer: CodecArg = None,
              partitions: int = None,
              retention: Seconds = None,
              compacting: bool = None,
              deleting: bool = None,
              replicas: int = None,
              acks: bool = True,
              internal: bool = False,
              config: Mapping[str, Any] = None,
              maxsize: int = None,
              allow_empty: bool = False,
              loop: asyncio.AbstractEventLoop = None) -> TopicT:
        ...

    @abc.abstractmethod
    def channel(self,
                *,
                key_type: ModelArg = None,
                value_type: ModelArg = None,
                maxsize: int = None,
                loop: asyncio.AbstractEventLoop = None) -> ChannelT:
        ...

    @abc.abstractmethod
    def agent(self,
              channel: Union[str, ChannelT] = None,
              *,
              name: str = None,
              concurrency: int = 1,
              supervisor_strategy: Type[SupervisorStrategyT] = None,
              sink: Iterable[SinkT] = None,
              isolated_partitions: bool = False,
              **kwargs: Any) -> Callable[[AgentFun], AgentT]:
        ...

    @abc.abstractmethod
    def task(self, fun: TaskArg) -> Callable:
        ...

    @abc.abstractmethod
    def timer(self, interval: Seconds, on_leader: bool = False) -> Callable:
        ...

    @abc.abstractmethod
    def crontab(self, cron_format: str, *,
                timezone: tzinfo = None,
                on_leader: bool = False) -> Callable:
        ...

    @abc.abstractmethod
    def service(self, cls: Type[ServiceT]) -> Type[ServiceT]:
        ...

    @abc.abstractmethod
    def stream(self,
               channel: AsyncIterable,
               beacon: NodeT = None,
               **kwargs: Any) -> StreamT:
        ...

    @abc.abstractmethod
    def Table(self,
              name: str,
              *,
              default: Callable[[], Any] = None,
              window: WindowT = None,
              partitions: int = None,
              help: str = None,
              **kwargs: Any) -> TableT:
        ...

    @abc.abstractmethod
    def page(self, path: str, *,
             base: Type[View] = View,
             name: str = None) -> Callable[[PageArg], Type[View]]:
        ...

    @abc.abstractmethod
    def table_route(self, table: CollectionT,
                    shard_param: str = None,
                    *,
                    query_param: str = None,
                    match_info: str = None) -> ViewDecorator:
        ...

    @abc.abstractmethod
    def command(self,
                *options: Any,
                base: Type[AppCommand] = None,
                **kwargs: Any) -> Callable[[Callable], Type[AppCommand]]:
        ...

    @abc.abstractmethod
    async def start_client(self) -> None:
        ...

    @abc.abstractmethod
    async def maybe_start_client(self) -> None:
        ...

    @abc.abstractmethod
    async def send(
            self,
            channel: Union[ChannelT, str],
            key: K = None,
            value: V = None,
            partition: int = None,
            key_serializer: CodecArg = None,
            value_serializer: CodecArg = None,
            callback: MessageSentCallback = None) -> Awaitable[RecordMetadata]:
        ...

    @stampede
    @abc.abstractmethod
    async def maybe_start_producer(self) -> ProducerT:
        ...

    @abc.abstractmethod
    def is_leader(self) -> bool:
        ...

    @abc.abstractmethod
    def FlowControlQueue(
            self,
            maxsize: int = None,
            *,
            clear_on_resume: bool = False,
            loop: asyncio.AbstractEventLoop = None) -> ThrowableQueue:
        ...

    @abc.abstractmethod
    def Worker(self, **kwargs: Any) -> WorkerT:
        ...

    @abc.abstractmethod
    def on_webserver_init(self, web: Web) -> None:
        ...

    @property
    def conf(self) -> Settings:
        ...

    @conf.setter
    def conf(self, settings: Settings) -> None:
        ...

    @property
    @abc.abstractmethod
    def transport(self) -> TransportT:
        ...

    @transport.setter
    def transport(self, transport: TransportT) -> None:
        ...

    @property
    @abc.abstractmethod
    def cache(self) -> CacheBackendT:
        ...

    @cache.setter
    def cache(self, cache: CacheBackendT) -> None:
        ...

    @property
    @abc.abstractmethod
    def producer(self) -> ProducerT:
        ...

    @property
    @abc.abstractmethod
    def consumer(self) -> ConsumerT:
        ...

    @cached_property
    @abc.abstractmethod
    def tables(self) -> TableManagerT:
        ...

    @cached_property
    @abc.abstractmethod
    def topics(self) -> ConductorT:
        ...

    @property
    @abc.abstractmethod
    def monitor(self) -> Monitor:
        ...

    @monitor.setter
    def monitor(self, value: Monitor) -> None:
        ...

    @cached_property
    @abc.abstractmethod
    def flow_control(self) -> FlowControlEvent:
        return FlowControlEvent(loop=self.loop)

    @property
    @abc.abstractmethod
    def http_client(self) -> HttpClientT:
        ...

    @http_client.setter
    def http_client(self, client: HttpClientT) -> None:
        ...

    @property
    @abc.abstractmethod
    def assignor(self) -> PartitionAssignorT:
        ...

    @property
    @abc.abstractmethod
    def router(self) -> RouterT:
        ...

    @property
    @abc.abstractmethod
    def serializers(self) -> RegistryT:
        ...

    @property
    @abc.abstractmethod
    def web(self) -> Web:
        ...

    @web.setter
    def web(self, web: Web) -> None:
        ...
Beispiel #3
0
class RobustSerialService(Service):
    on_data: SignalT = Signal()
    on_connection_made: SignalT = Signal()
    on_connection_lost: SignalT = Signal()

    def __init__(self,
                 device,
                 baudrate=115200,
                 timeout=1,
                 protocol_factory=JanusLineReader,
                 **kwargs) -> None:
        super().__init__(**kwargs)

        self._device = device
        self.baudrate = baudrate
        self.timeout = timeout

        self.on_data = self.on_data.with_default_sender(self)
        self.on_connection_made = self.on_connection_made.with_default_sender(
            self)
        self.on_connection_lost = self.on_connection_lost.with_default_sender(
            self)

        self.read_queue = janus.Queue(loop=self.loop)
        self.set_protocol_factory(protocol_factory)

    def set_protocol_factory(self, protocol_factory):
        self._protocol_factory = protocol_factory

    def make_bound_parser(self, *arg, **kwds):
        protocol = self._protocol_factory(*arg, **kwds)
        protocol.parent = self
        return protocol

    async def on_start(self):
        # self.log.info(f'RobustSerialService: {self.device} in thread {threading.get_ident()}')
        self.log.info(f'Starting on {self.device}')

        try:
            ser = serial.serial_for_url(self.device,
                                        baudrate=self.baudrate,
                                        timeout=self.timeout)
            self.reader_thread = self.add_context(
                ReaderThread(ser, self.make_bound_parser))
        except BaseException as e:
            self.log.warning(f'Problems opening port! Stopping! ({str(e)})')
            await self.stop()

    async def on_stop(self) -> None:
        self.log.info('RobustSerialService on_stop')

    async def transform_data(self, data_raw):
        ''' override this fuction in a subclass to refine data analysis '''
        return data_raw

    @property
    def read_queue_sync(self):
        return self.read_queue.sync_q

    @Service.task
    async def _pump_data(self) -> None:
        self.log.debug('pump_data TASK STARTING')
        while not self.should_stop:
            data = await self.read_queue.async_q.get()
            if type(data) == SerialData:
                self.log.debug(
                    f'async thread {threading.get_ident()}: SerialData: {data["data_raw"]}'
                )
                trafo_data = await self.transform_data(data["data_raw"])
                await self.on_data.send(data=trafo_data)
            elif type(data) == EventConnectionMade:
                self.log.debug(
                    f'async thread {threading.get_ident()}: EventConnectionMade'
                )
                await self.on_connection_made.send()
            elif type(data) == EventConnectionLost:
                self.log.debug(
                    f'async thread {threading.get_ident()}: EventConnectionLost'
                )
                await self.on_connection_lost.send()
                await self.crash(RuntimeError('Connection lost!'))

    @property
    def device(self):
        return self._device

    @property
    def shortlabel(self) -> str:
        """Label used for logging."""
        if self.device is not None:
            return super().shortlabel + '-' + self.device
        return super().shortlabel