def get_data_from_proto(request): data_type = request.WhichOneof("data_oneof") if data_type == "data": datadef = request.data return grpc_datadef_to_array(datadef) elif data_type == "binData": return request.binData elif data_type == "strData": return request.strData else: raise SeldonMicroserviceException("Unknown data in SeldonMessage")
def Predict(self, request, context): if hasattr(self.user_model, "predict_grpc"): return self.user_model.predict_grpc(request) else: features = get_data_from_proto(request) meta = get_meta_from_proto(request) datadef = request.data data_type = request.WhichOneof("data_oneof") predictions = predict(self.user_model, features, datadef.names, meta=meta) # Construct meta data meta = prediction_pb2.Meta() metaJson = {} tags = get_custom_tags(self.user_model) if tags: metaJson["tags"] = tags metrics = get_custom_metrics(self.user_model) if metrics: metaJson["metrics"] = metrics json_format.ParseDict(metaJson, meta) if isinstance(predictions, np.ndarray) or data_type == "data": predictions = np.array(predictions) if len(predictions.shape) > 1: class_names = get_class_names(self.user_model, predictions.shape[1]) else: class_names = [] if data_type == "data": default_data_type = request.data.WhichOneof("data_oneof") else: default_data_type = "tensor" data = array_to_grpc_datadef(predictions, class_names, default_data_type) return prediction_pb2.SeldonMessage(data=data, meta=meta) else: return prediction_pb2.SeldonMessage(binData=predictions, meta=meta)
def manage_stock(context, request: typing.Union[StockRequest, CreateItemRequest, OrderAddItemStockRequest]): # Get the current state. item_state: ItemData = context.state('item').unpack(ItemData) if isinstance(request, CreateItemRequest): item_state = ItemData() item_state.id = request.id item_state.price = request.price item_state.stock = 0 context.state('item').pack(item_state) #logger.debug(f'Created new item with id {request.id}') response = ResponseMessage() response.result = json.dumps({'item_id': item_state.id}) elif isinstance(request, OrderAddItemStockRequest): response = None if item_state is None: pass else: item_state.stock += request.amount context.state('item').pack(item_state) elif isinstance(request, StockRequest): # If the item state is None we return an error if item_state is None: # Item does not exist yet. Return error. if not request.internal: response = ResponseMessage() response.result = json.dumps({'result': 'not_found'}) else: response = StockResponse() response.item_id = request.subtract_stock.id response.result = 'failure' else: # check which field we have msg_type = request.WhichOneof('message') #logger.debug(f'Got message of type {msg_type}') if msg_type == "find_item": response = ResponseMessage() response.result = json.dumps( {'id:': item_state.id, 'price': item_state.price, 'stock': item_state.stock}) context.state('item').pack(item_state) elif msg_type == "subtract_stock": new_amount = item_state.stock - request.subtract_stock.amount if not request.internal: response = ResponseMessage() else: response = StockResponse() if new_amount >= 0: item_state.stock -= request.subtract_stock.amount context.state('item').pack(item_state) if not request.internal: response.result = json.dumps({'result': 'success', 'item_id': item_state.id}) else: # Include the item id and price response.price = item_state.price response.item_id = item_state.id response.result = 'success' else: if not request.internal: response.result = json.dumps({'result': 'stock too low', 'item_id': item_state.id}) else: response.price = item_state.price response.item_id = item_state.id response.result = 'failure' elif msg_type == "add_stock": item_state.stock += request.add_stock.amount context.state('item').pack(item_state) # send the response. response = ResponseMessage() response.result = json.dumps({'result': 'success', 'item_id': item_state.id}) if response: # Use the same request id in the message body # and use the request worker_id as key of the message if not request.internal: response.request_id = request.request_info.request_id # create the egress message and send it to the # users/out egress egress_message = kafka_egress_record( topic=STOCK_EVENTS_TOPIC, key=request.request_info.worker_id, value=response ) context.pack_and_send_egress("stock/out", egress_message) else: response.request_info.request_id = request.request_info.request_id response.request_info.worker_id = request.request_info.worker_id context.pack_and_send("orders/order", str(request.order_id), response)
def operate_user(context, request: typing.Union[UserPayRequest, UserCancelPayRequest, UserRequest, CreateUserRequest]): """ Does all the operations with a single user Has the state of a user in a UserData() object that includes its id and credit under the name 'user' """ # Get the current state for a given user # could have to handle the state not existing for this user state: UserData = context.state('user').unpack(UserData) response = None # ---------------------------------------- # Messages from the payment endpoint # ---------------------------------------- if isinstance(request, UserPayRequest): #logger.debug('Received request to decrement user credit') # calculate if the credit is enough to pay for the product # get the credit response = UserPayResponse() response.order_id = request.order_id # copy the information of the request_info response = copy_request_info(request, response) # if the user exists then do the checks if state: # see whether we should return success or failure if state.credit - request.amount < 0: response.success = False else: state.credit -= request.amount response.success = True else: response.success = False # pack the state context.state('user').pack(state) # respond to the payment service context.pack_and_reply(response) return elif isinstance(request, UserCancelPayRequest): #logger.debug('Received request to cancel a payment') # add the amount specified to the user credit response = UserPayResponse() response.order_id = request.order_id # copy the information response = copy_request_info(request, response) if state: state.credit += request.amount # reply response.success = True else: response.success = False # pack the state context.state('user').pack(state) # reply to the sender function context.pack_and_reply(response) return # ------------------------------------- # Interaction with the user endpoint # ------------------------------------- elif isinstance(request, CreateUserRequest): # we are given the uuid in the message so that's already done state = UserData() state.id = request.id state.credit = 0 #logger.debug(f'Created new user with id {request.id}') context.state('user').pack(state) response = ResponseMessage() response.result = json.dumps({'user_id': state.id}) elif isinstance(request, UserRequest): # check which field we have msg_type = request.WhichOneof('message') #logger.debug(f'Got message of type {msg_type}') # If the state is None we return an error if not state: response = ResponseMessage() response.result = json.dumps( {'result': 'failure: user does not exist'}) else: # If the state exists we then operate with it if msg_type == 'find_user': response = ResponseMessage() response.result = json.dumps({ 'user_id': state.id, 'credit': state.credit }) # pack the state context.state('user').pack(state) elif msg_type == 'remove_user': del context['user'] response = ResponseMessage() response.result = json.dumps({'result': 'success'}) elif msg_type == 'add_credit': # Update the credit and save state state.credit += request.add_credit.amount context.state('user').pack(state) # send the response response = ResponseMessage() response.result = json.dumps({'result': 'success'}) elif msg_type == 'subtract_credit': # try to subtract the amount from the user credit new_amount = state.credit - request.subtract_credit.amount response = ResponseMessage() if new_amount >= 0: state.credit -= request.subtract_credit.amount context.state('user').pack(state) response.result = json.dumps({'result': 'success'}) else: response.result = json.dumps({'result': 'failure'}) else: logger.error('Received unknown message type!') # respond if needed if response: # Use the same request id in the message body # and use the request worker_id as key of the message response.request_id = request.request_info.request_id # create the egress message and send it to the # users/out egress egress_message = kafka_egress_record( topic=USER_EVENTS_TOPIC, key=request.request_info.worker_id, value=response) context.pack_and_send_egress("users/out", egress_message)