async def start(self, output: Queue) -> None: msg = proto.CreatePersistentSubscription() msg.subscription_group_name = self.name msg.event_stream_id = self.stream msg.start_from = self.start_from msg.resolve_link_tos = self.resolve_links msg.message_timeout_milliseconds = self.timeout_ms msg.record_statistics = self.record_statistics msg.live_buffer_size = self.live_buffer_size msg.read_batch_size = self.read_batch_size msg.buffer_size = self.buffer_size msg.max_retry_count = self.max_retry_count msg.prefer_round_robin = self.prefer_round_robin msg.checkpoint_after_time = self.checkpoint_after_time msg.checkpoint_max_count = self.checkpoint_max_count msg.checkpoint_min_count = self.checkpoint_min_count msg.subscriber_max_count = self.subscriber_max_count msg.named_consumer_strategy = self.consumer_strategy await output.put( OutboundMessage( self.conversation_id, TcpCommand.CreatePersistentSubscription, msg.SerializeToString(), self.credential, ))
async def start(self, output: Queue) -> None: msg = proto.WriteEvents() msg.event_stream_id = self.stream msg.require_master = self.require_master msg.expected_version = self.expected_version for event in self.events: e = msg.events.add() e.event_id = event.id.bytes_le e.event_type = event.type if isinstance(event.data, str): e.data_content_type = ContentType.Json e.data = event.data.encode("UTF-8") elif event.data: e.data_content_type = ContentType.Json e.data = json.dumps(event.data).encode("UTF-8") else: e.data_content_type = ContentType.Binary e.data = bytes() if event.metadata: e.metadata_content_type = ContentType.Json e.metadata = json.dumps(event.metadata).encode("UTF-8") else: e.metadata_content_type = ContentType.Binary e.metadata = bytes() data = msg.SerializeToString() await output.put( OutboundMessage(self.conversation_id, TcpCommand.WriteEvents, data, self.credential))
async def start(self, output: Queue) -> Future: await super().start(output) if output: await output.put( OutboundMessage(self.conversation_id, TcpCommand.Ping, b"", self.credential)) return self.result
async def ack(self, event): payload = proto.PersistentSubscriptionAckEvents() payload.subscription_id = self.name payload.processed_event_ids.append(event.original_event_id.bytes_le) message = OutboundMessage( self.conversation_id, TcpCommand.PersistentSubscriptionAckEvents, payload.SerializeToString(), ) await self.out_queue.put(message)
async def start(self, output: Queue) -> None: msg = proto.SubscribeToStream() msg.event_stream_id = self.stream msg.resolve_link_tos = self.resolve_link_tos await output.put( OutboundMessage( self.conversation_id, TcpCommand.SubscribeToStream, msg.SerializeToString(), self.credential, ))
async def start(self, output: Queue) -> None: msg = proto.ReadEvent() msg.event_number = self.event_number msg.event_stream_id = self.stream msg.require_master = self.require_master msg.resolve_link_tos = self.resolve_link_tos data = msg.SerializeToString() await output.put( OutboundMessage(self.conversation_id, TcpCommand.Read, data, self.credential))
async def start(self, output: Queue) -> None: msg = proto.ConnectToPersistentSubscription() msg.subscription_id = self.name msg.event_stream_id = self.stream msg.allowed_in_flight_messages = self.max_in_flight await output.put( OutboundMessage( self.conversation_id, TcpCommand.ConnectToPersistentSubscription, msg.SerializeToString(), self.credential, ))
def _fetch_page_message(self, from_event): if self.direction == StreamDirection.Forward: command = TcpCommand.ReadStreamEventsForward else: command = TcpCommand.ReadStreamEventsBackward msg = proto.ReadStreamEvents() msg.event_stream_id = self.stream msg.from_event_number = from_event msg.max_count = self.max_count msg.require_master = self.require_master msg.resolve_link_tos = self.resolve_link_tos data = msg.SerializeToString() return OutboundMessage(self.conversation_id, command, data, self.credential)
async def start(self, output: Queue) -> Future: await super().start(output) if self.direction == Heartbeat.INBOUND: one_way = True cmd = TcpCommand.HeartbeatResponse else: one_way = False cmd = TcpCommand.HeartbeatRequest await output.put( OutboundMessage( self.conversation_id, cmd, b"", self.credential, one_way=one_way ) )
async def test_when_sending_a_heartbeat_request(): """ Periodically, the Pacemaker sends a heartbeat request to the server. """ heartbeat_id = uuid.uuid4() out_queue = TeeQueue() pace_maker = PaceMaker(out_queue, None, heartbeat_id=heartbeat_id) await pace_maker.send_heartbeat() [request] = out_queue.items assert request == OutboundMessage( heartbeat_id, TcpCommand.HeartbeatRequest, bytes() )
def _fetch_page_message(self, from_position): if self.direction == StreamDirection.Forward: command = TcpCommand.ReadAllEventsForward else: command = TcpCommand.ReadAllEventsBackward msg = proto.ReadAllEvents() msg.commit_position = from_position.commit msg.prepare_position = from_position.prepare msg.max_count = self.batch_size msg.resolve_link_tos = self.resolve_link_tos msg.require_master = self.require_master data = msg.SerializeToString() return OutboundMessage(self.conversation_id, command, data, self.credential)
async def test_when_running_a_persistent_subscription(): """ We ought to be able to connect a persistent subscription, and receive some events. """ dispatcher = MessageDispatcher() out_queue = TeeQueue() conversation = ConnectPersistentSubscription("my-sub", "my-stream") first_msg = persistent_subscription_confirmed(conversation.conversation_id, "my-sub") # The subscription confirmed message should result in our having a # PersistentSubscription to play with. future = await dispatcher.start_conversation(conversation) await dispatcher.dispatch(first_msg, out_queue) subscription = await asyncio.wait_for(future, 1) # A subsequent PersistentSubscriptionStreamEventAppeared message should # enqueue the event onto our iterator await dispatcher.dispatch( subscription_event_appeared(conversation.conversation_id, NewEvent("event", data={"x": 2})), out_queue, ) event = await anext(subscription.events) assert event.json()["x"] == 2 # Acknowledging the event should place an Ack message on the out_queue await subscription.ack(event) expected_payload = proto.PersistentSubscriptionAckEvents() expected_payload.subscription_id = "my-sub" expected_payload.processed_event_ids.append(event.event.id.bytes_le) expected_message = OutboundMessage( conversation.conversation_id, TcpCommand.PersistentSubscriptionAckEvents, expected_payload.SerializeToString(), ) ack = await out_queue.get() assert ack == expected_message
async def test_when_receiving_a_heartbeat_request(): """ When we receive a HeartbeatRequest from the server, we should immediately respond with a HeartbeatResponse """ out_queue = TeeQueue() pace_maker = PaceMaker(out_queue, None) heartbeat_id = uuid.uuid4() await pace_maker.handle_request( InboundMessage(heartbeat_id, TcpCommand.HeartbeatRequest, bytes()) ) response = await out_queue.get() assert response == OutboundMessage( heartbeat_id, TcpCommand.HeartbeatResponse, bytes() )
def _fetch_page_message(self, from_position: Position): self._logger.debug("Requesting page of %d events from %s", self.max_count, from_position) if self.direction == StreamDirection.Forward: command = TcpCommand.ReadAllEventsForward else: command = TcpCommand.ReadAllEventsBackward msg = proto.ReadAllEvents() msg.commit_position = from_position.commit msg.prepare_position = from_position.prepare msg.max_count = self.max_count msg.require_master = self.require_master msg.resolve_link_tos = self.resolve_link_tos data = msg.SerializeToString() return OutboundMessage(self.conversation_id, command, data, self.credential)