Example #1
0
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)
Example #3
0
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)
Example #4
0
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)