def start(self, known_ids=None): """Subscribes to state delta events, and then waits to receive deltas. Sends any events received to delta handlers. """ if not known_ids: known_ids = [NULL_BLOCK_ID] self._stream.wait_for_ready() LOGGER.debug('Subscribing to state delta events') block_sub = EventSubscription(event_type='sawtooth/block-commit') delta_sub = EventSubscription( event_type='sawtooth/state-delta', filters=[ EventFilter(key='address', match_string='^{}.*'.format(NAMESPACE), filter_type=EventFilter.REGEX_ANY) ]) request = ClientEventsSubscribeRequest( last_known_block_ids=known_ids, subscriptions=[block_sub, delta_sub]) response_future = self._stream.send( Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, request.SerializeToString()) response = ClientEventsSubscribeResponse() response.ParseFromString(response_future.result().content) # Forked all the way back to genesis, restart with no known_ids if (response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK and known_ids): return self.start() if response.status != ClientEventsSubscribeResponse.OK: raise RuntimeError('Subscription failed with status: {}'.format( ClientEventsSubscribeResponse.Status.Name(response.status))) self._is_active = True LOGGER.debug('Successfully subscribed to state delta events') while self._is_active: message_future = self._stream.receive() event_list = EventList() event_list.ParseFromString(message_future.result().content) for handler in self._event_handlers: handler(event_list.events)
async def subscribe_events(self, web_sock, last_known_block_id=None): # Setup a connection to the validator LOGGER.debug(f"Subscription started") request = ClientEventsSubscribeRequest( subscriptions=self._make_subscriptions(), last_known_block_ids=[last_known_block_id] if last_known_block_id else []).SerializeToString() # Construct the message wrapper correlation_id = generate_random_key( ) # This must be unique for all in-process requests msg = Message(correlation_id=correlation_id, message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, content=request) # Send the request LOGGER.debug(f"Sending subscription request.") await self._loop.run_in_executor( None, lambda: self._socket.send_multipart([msg.SerializeToString()])) LOGGER.debug(f"Subscription request is sent") msg = await self._event_queue[Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE ].get() LOGGER.info(f"message type {msg.message_type}") # Validate the response type if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE: LOGGER.error(f"Skip unexpected message type") return # Parse the response response = ClientEventsSubscribeResponse() response.ParseFromString(msg.content) # Validate the response status if response.status != ClientEventsSubscribeResponse.OK: if response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK: raise SocketException( web_sock, Status.UNKNOWN_BLOCK, f"Uknown block in: {last_known_block_id}") raise SocketException( web_sock, 0, "Subscription failed: Couldn't send multipart") LOGGER.debug(f"Successfully subscribed")
def set_up_zmq_subscription(): """ This sends a subscription request to ZMQ. See: https://sawtooth.hyperledger.org/docs/core/ releases/latest/app_developers_guide/zmq_event_subscription.html """ subscription = EventSubscription( event_type="sawtooth/state-delta", filters=[ EventFilter( key="address", match_string="b89bcb.*", filter_type=EventFilter.REGEX_ANY) ]) request = ClientEventsSubscribeRequest( subscriptions=[subscription] ).SerializeToString() correlation_id = "123" # This must be unique for all in-process requests msg = Message( correlation_id=correlation_id, message_type=Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_REQUEST, content=request ) socket.send_multipart([msg.SerializeToString()]) resp = socket.recv_multipart()[-1] msg = Message() msg.ParseFromString(resp) if msg.message_type != \ Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_RESPONSE: print("Unexpected message type") exit(1) response = ClientEventsSubscribeResponse() response.ParseFromString(msg.content) if response.status != ClientEventsSubscribeResponse.OK: print("Subscription failed: {}".format(response.response_message)) exit(1) LOGGER.debug("Setting up ZMQ subscription successful")
def subscribe_to_event(self): LOGGER.info("Subscribing to event {}".format(self._event)) done_sub = EventSubscription(event_type=self._event) request = ClientEventsSubscribeRequest(subscriptions=[done_sub]) response_future = self._stream.send( Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, request.SerializeToString()) sub_response = ClientEventsSubscribeResponse() sub_response.ParseFromString(response_future.result().content) if sub_response.status == ClientEventsSubscribeResponse.OK: self._is_active = True LOGGER.info('Subscription with response {}'.format( sub_response.status)) else: LOGGER.error('Could not Subscribe to event') raise SubscriberError()
def listen_to_event(self): self._stream.wait_for_ready() # Step 1: Construct a Subscription block_sub = EventSubscription(event_type='sawtooth/block-commit') # Step 2: Submit the Event Subscription request = ClientEventsSubscribeRequest(subscriptions=[block_sub]) response_future = self._stream.send( Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, request.SerializeToString()) response = ClientEventsSubscribeResponse() response.ParseFromString(response_future.result().content) # Listen for events in an infinite loop LOGGER.warning("Listening to events.") while True: msg = self._stream.receive() event_list = EventList() event_list.ParseFromString(msg.result().content) for handler in self._event_handlers: handler(event_list.events)
async def subscribe(request): ws = request.ws if ws is None: raise ClientException( message='Subscription available only through websocket') msg_id = request.msg.data['id'] request.params = request.params or {} try: event_type = request.params['event_type'] except KeyError as e: raise RpcInvalidParamsError(message='Missed event_type') try: evt_tr = EVENT_HANDLERS[event_type] except KeyError: raise ClientException(message=f'Event "{event_type}" not defined') async with event_lock: subsevt = request.rpc._subsevt.setdefault(ws, {}) if event_type in subsevt: raise ClientException( message=f'Already subscribed to event "{event_type}"') router = ws.stream.router event_types = set(subsevt.keys()) event_types.add(event_type) LOGGER.debug(f'Events to re-subsribe: {event_types}') validated_data = evt_tr.validate(msg_id, request.params) from_block = validated_data.get('from_block') if not from_block: from_block = (await router.list_blocks(limit=1))['head'] req_msg = evt_tr.prepare_subscribe_message(event_types, from_block) LOGGER.debug(f'Request message: {req_msg}') msg = await ws.stream.send( message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, message_content=req_msg.SerializeToString(), timeout=ZMQ_CONNECTION_TIMEOUT) LOGGER.debug(f'Message type: {msg.message_type}') # Validate the response type if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE: raise ClientException( message=f'Unexpected message type {msg.message_type}') # Parse the response response = ClientEventsSubscribeResponse() response.ParseFromString(msg.content) # Validate the response status if response.status != ClientEventsSubscribeResponse.OK: if response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK: raise ClientException(message=f'Unknown block "{from_block}"') raise ClientException(message='Subscription failed: Couldn\'t ' 'send multipart') if ws not in request.rpc._evthashes: request.rpc._evthashes[ws] = set() LOGGER.debug(f'Create cosumer task for {ws}') request.rpc.loop.create_task(_consumer(request)) if event_type == 'batch': LOGGER.debug(f'Create producer task for {ws}') request.rpc.loop.create_task(_producer(request)) subsevt[event_type] = { 'msg_id': msg_id, 'validated_data': validated_data, } return 'SUBSCRIBED'
def subscribe(self, event_name: str, is_write_to_file=False, file_name='certificate.pem'): subscription = EventSubscription(event_type="ca_1/{}".format(event_name)) # Setup a connection to the validator ctx = zmq.Context() socket = ctx.socket(zmq.DEALER) socket.connect('tcp://127.0.0.1:4004') # Construct the request request = ClientEventsSubscribeRequest( subscriptions=[subscription]).SerializeToString() # Construct the message wrapper correlation_id = "123" # This must be unique for all in-process requests msg = Message( correlation_id=correlation_id, message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, content=request) # Send the request socket.send_multipart([msg.SerializeToString()]) # Receive the response resp = socket.recv_multipart()[-1] # Parse the message wrapper msg = Message() msg.ParseFromString(resp) # Validate the response type if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE: print("Unexpected message type") return # Parse the response response = ClientEventsSubscribeResponse() response.ParseFromString(msg.content) # Validate the response status if response.status != ClientEventsSubscribeResponse.OK: print("Subscription failed: {}".format(response.response_message)) return resp = socket.recv_multipart()[-1] # Parse the message wrapper msg = Message() msg.ParseFromString(resp) # Validate the response type if msg.message_type != Message.CLIENT_EVENTS: print("Unexpected message type") return # Parse the response events = EventList() events.ParseFromString(msg.content) for event in events.events: if event.data is not None: if is_write_to_file: write_to_file(file_name, event.data) else: print(event.data) # Construct the request request = ClientEventsUnsubscribeRequest().SerializeToString() # Construct the message wrapper correlation_id = "124" # This must be unique for all in-process requests msg = Message( correlation_id=correlation_id, message_type=Message.CLIENT_EVENTS_UNSUBSCRIBE_REQUEST, content=request) # Send the request socket.send_multipart([msg.SerializeToString()]) # Receive the response resp = socket.recv_multipart()[-1] # Parse the message wrapper msg = Message() msg.ParseFromString(resp) # Validate the response type if msg.message_type != Message.CLIENT_EVENTS_UNSUBSCRIBE_RESPONSE: print("Unexpected message type") # Parse the response response = ClientEventsUnsubscribeResponse() response.ParseFromString(msg.content) # Validate the response status if response.status != ClientEventsUnsubscribeResponse.OK: print("Unsubscription failed: {}".format(response.response_message)) # Close the connection to the validator socket.close()
def subscribe_event(): """ A custom management command to store block information of each block data by event subscription. this command is calling from docker-compose file """ logger.info("event function start..") # Setup a connection to the validator ctx = zmq.Context() socket = ctx.socket(zmq.DEALER) socket.connect(validator_url) # -------------------------------# # Submit the Event Subscription # # -------------------------------# # subscribe both both "block commit" and "state-delta" event block_sub = EventSubscription(event_type='sawtooth/block-commit') delta_sub = EventSubscription( event_type='sawtooth/state-delta', filters=[ EventFilter(key='address', match_string='^{}.*'.format(NAMESPACE), filter_type=EventFilter.REGEX_ANY) ]) # Construct the request request = ClientEventsSubscribeRequest( subscriptions=[block_sub, delta_sub]).SerializeToString() # Construct the message wrapper correlation_id = "123" # This must be unique for all in-process requests msg = Message(correlation_id=correlation_id, message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST, content=request) # Send the request socket.send_multipart([msg.SerializeToString()]) # # -------------------------------# # Receive the response # # -------------------------------# resp = socket.recv_multipart()[-1] # Parse the message wrapper msg = Message() msg.ParseFromString(resp) # Validate the response type if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE: logger.error("Unexpected message type") return # Parse the response response = ClientEventsSubscribeResponse() response.ParseFromString(msg.content) # Validate the response status if response.status != ClientEventsSubscribeResponse.OK: return while True: resp = socket.recv_multipart()[-1] # Parse the message wrapper msg = Message() msg.ParseFromString(resp) # Validate the response type if msg.message_type != Message.CLIENT_EVENTS: return # Parse the response events = EventList() events.ParseFromString(msg.content) block_info = {"address": []} event_data = MessageToDict(events) events_list = event_data["events"] for event in events_list: attributes = event["attributes"] for attr in attributes: key = attr["key"] value = attr["value"] if key == 'address': block_info["address"].append(value) else: block_info[key] = value address_list = block_info["address"] for address in address_list: BlockInfo.objects.create( block_num=block_info["block_num"], block_id=block_info["block_id"], state_root_hash=block_info["state_root_hash"], previous_block_id=block_info["previous_block_id"], address=address, ) logger.info("blockinfo subscription created..")