initial commit
Some checks failed
SonarQube Analysis / Build, Test & Analyse (push) Has been cancelled
Build and Publish TechDocs / build-and-publish (push) Has been cancelled

Change-Id: I12a20fc994c2a94df96de9d3393b06bf6687f77a
This commit is contained in:
Scaffolder
2026-04-17 11:20:50 +00:00
commit 4e3fd72697
376 changed files with 53620 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Define a default value so it's not empty if the builder fails to provide it
ARG BUILDPLATFORM=linux/amd64
FROM --platform=$BUILDPLATFORM python:3.14.3-alpine@sha256:faee120f7885a06fcc9677922331391fa690d911c020abb9e8025ff3d908e510 AS base
FROM base AS builder
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN apk update \
&& apk add --no-cache g++ linux-headers \
&& rm -rf /var/cache/apk/*
# get packages
COPY requirements.txt .
RUN pip install -r requirements.txt
FROM base
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN apk update \
&& apk add --no-cache libstdc++ \
&& rm -rf /var/cache/apk/*
# get packages
WORKDIR /recommendationservice
# Grab packages from builder
COPY --from=builder /usr/local/lib/python3.14/ /usr/local/lib/python3.14/
# Add the application
COPY . .
# set listen port
ENV PORT="8080"
EXPOSE 8080
ENTRYPOINT ["python", "recommendation_server.py"]

View File

@@ -0,0 +1,39 @@
#!/usr/bin/python
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import grpc
import demo_pb2
import demo_pb2_grpc
from logger import getJSONLogger
logger = getJSONLogger('recommendationservice-server')
if __name__ == "__main__":
# get port
if len(sys.argv) > 1:
port = sys.argv[1]
else:
port = "8080"
# set up server stub
channel = grpc.insecure_channel('localhost:'+port)
stub = demo_pb2_grpc.RecommendationServiceStub(channel)
# form request
request = demo_pb2.ListRecommendationsRequest(user_id="test", product_ids=["test"])
# make call to server
response = stub.ListRecommendations(request)
logger.info(response)

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,822 @@
#!/usr/bin/python
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import demo_pb2 as demo__pb2
class CartServiceStub(object):
"""-----------------Cart service-----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.AddItem = channel.unary_unary(
'/hipstershop.CartService/AddItem',
request_serializer=demo__pb2.AddItemRequest.SerializeToString,
response_deserializer=demo__pb2.Empty.FromString,
)
self.GetCart = channel.unary_unary(
'/hipstershop.CartService/GetCart',
request_serializer=demo__pb2.GetCartRequest.SerializeToString,
response_deserializer=demo__pb2.Cart.FromString,
)
self.EmptyCart = channel.unary_unary(
'/hipstershop.CartService/EmptyCart',
request_serializer=demo__pb2.EmptyCartRequest.SerializeToString,
response_deserializer=demo__pb2.Empty.FromString,
)
class CartServiceServicer(object):
"""-----------------Cart service-----------------
"""
def AddItem(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetCart(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def EmptyCart(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CartServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'AddItem': grpc.unary_unary_rpc_method_handler(
servicer.AddItem,
request_deserializer=demo__pb2.AddItemRequest.FromString,
response_serializer=demo__pb2.Empty.SerializeToString,
),
'GetCart': grpc.unary_unary_rpc_method_handler(
servicer.GetCart,
request_deserializer=demo__pb2.GetCartRequest.FromString,
response_serializer=demo__pb2.Cart.SerializeToString,
),
'EmptyCart': grpc.unary_unary_rpc_method_handler(
servicer.EmptyCart,
request_deserializer=demo__pb2.EmptyCartRequest.FromString,
response_serializer=demo__pb2.Empty.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.CartService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class CartService(object):
"""-----------------Cart service-----------------
"""
@staticmethod
def AddItem(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/AddItem',
demo__pb2.AddItemRequest.SerializeToString,
demo__pb2.Empty.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetCart(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/GetCart',
demo__pb2.GetCartRequest.SerializeToString,
demo__pb2.Cart.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def EmptyCart(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/EmptyCart',
demo__pb2.EmptyCartRequest.SerializeToString,
demo__pb2.Empty.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class RecommendationServiceStub(object):
"""---------------Recommendation service----------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.ListRecommendations = channel.unary_unary(
'/hipstershop.RecommendationService/ListRecommendations',
request_serializer=demo__pb2.ListRecommendationsRequest.SerializeToString,
response_deserializer=demo__pb2.ListRecommendationsResponse.FromString,
)
class RecommendationServiceServicer(object):
"""---------------Recommendation service----------
"""
def ListRecommendations(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_RecommendationServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'ListRecommendations': grpc.unary_unary_rpc_method_handler(
servicer.ListRecommendations,
request_deserializer=demo__pb2.ListRecommendationsRequest.FromString,
response_serializer=demo__pb2.ListRecommendationsResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.RecommendationService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class RecommendationService(object):
"""---------------Recommendation service----------
"""
@staticmethod
def ListRecommendations(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.RecommendationService/ListRecommendations',
demo__pb2.ListRecommendationsRequest.SerializeToString,
demo__pb2.ListRecommendationsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class ProductCatalogServiceStub(object):
"""---------------Product Catalog----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.ListProducts = channel.unary_unary(
'/hipstershop.ProductCatalogService/ListProducts',
request_serializer=demo__pb2.Empty.SerializeToString,
response_deserializer=demo__pb2.ListProductsResponse.FromString,
)
self.GetProduct = channel.unary_unary(
'/hipstershop.ProductCatalogService/GetProduct',
request_serializer=demo__pb2.GetProductRequest.SerializeToString,
response_deserializer=demo__pb2.Product.FromString,
)
self.SearchProducts = channel.unary_unary(
'/hipstershop.ProductCatalogService/SearchProducts',
request_serializer=demo__pb2.SearchProductsRequest.SerializeToString,
response_deserializer=demo__pb2.SearchProductsResponse.FromString,
)
class ProductCatalogServiceServicer(object):
"""---------------Product Catalog----------------
"""
def ListProducts(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetProduct(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SearchProducts(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_ProductCatalogServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'ListProducts': grpc.unary_unary_rpc_method_handler(
servicer.ListProducts,
request_deserializer=demo__pb2.Empty.FromString,
response_serializer=demo__pb2.ListProductsResponse.SerializeToString,
),
'GetProduct': grpc.unary_unary_rpc_method_handler(
servicer.GetProduct,
request_deserializer=demo__pb2.GetProductRequest.FromString,
response_serializer=demo__pb2.Product.SerializeToString,
),
'SearchProducts': grpc.unary_unary_rpc_method_handler(
servicer.SearchProducts,
request_deserializer=demo__pb2.SearchProductsRequest.FromString,
response_serializer=demo__pb2.SearchProductsResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.ProductCatalogService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class ProductCatalogService(object):
"""---------------Product Catalog----------------
"""
@staticmethod
def ListProducts(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/ListProducts',
demo__pb2.Empty.SerializeToString,
demo__pb2.ListProductsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetProduct(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/GetProduct',
demo__pb2.GetProductRequest.SerializeToString,
demo__pb2.Product.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def SearchProducts(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/SearchProducts',
demo__pb2.SearchProductsRequest.SerializeToString,
demo__pb2.SearchProductsResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class ShippingServiceStub(object):
"""---------------Shipping Service----------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetQuote = channel.unary_unary(
'/hipstershop.ShippingService/GetQuote',
request_serializer=demo__pb2.GetQuoteRequest.SerializeToString,
response_deserializer=demo__pb2.GetQuoteResponse.FromString,
)
self.ShipOrder = channel.unary_unary(
'/hipstershop.ShippingService/ShipOrder',
request_serializer=demo__pb2.ShipOrderRequest.SerializeToString,
response_deserializer=demo__pb2.ShipOrderResponse.FromString,
)
class ShippingServiceServicer(object):
"""---------------Shipping Service----------
"""
def GetQuote(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ShipOrder(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_ShippingServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetQuote': grpc.unary_unary_rpc_method_handler(
servicer.GetQuote,
request_deserializer=demo__pb2.GetQuoteRequest.FromString,
response_serializer=demo__pb2.GetQuoteResponse.SerializeToString,
),
'ShipOrder': grpc.unary_unary_rpc_method_handler(
servicer.ShipOrder,
request_deserializer=demo__pb2.ShipOrderRequest.FromString,
response_serializer=demo__pb2.ShipOrderResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.ShippingService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class ShippingService(object):
"""---------------Shipping Service----------
"""
@staticmethod
def GetQuote(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.ShippingService/GetQuote',
demo__pb2.GetQuoteRequest.SerializeToString,
demo__pb2.GetQuoteResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def ShipOrder(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.ShippingService/ShipOrder',
demo__pb2.ShipOrderRequest.SerializeToString,
demo__pb2.ShipOrderResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class CurrencyServiceStub(object):
"""-----------------Currency service-----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetSupportedCurrencies = channel.unary_unary(
'/hipstershop.CurrencyService/GetSupportedCurrencies',
request_serializer=demo__pb2.Empty.SerializeToString,
response_deserializer=demo__pb2.GetSupportedCurrenciesResponse.FromString,
)
self.Convert = channel.unary_unary(
'/hipstershop.CurrencyService/Convert',
request_serializer=demo__pb2.CurrencyConversionRequest.SerializeToString,
response_deserializer=demo__pb2.Money.FromString,
)
class CurrencyServiceServicer(object):
"""-----------------Currency service-----------------
"""
def GetSupportedCurrencies(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Convert(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CurrencyServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetSupportedCurrencies': grpc.unary_unary_rpc_method_handler(
servicer.GetSupportedCurrencies,
request_deserializer=demo__pb2.Empty.FromString,
response_serializer=demo__pb2.GetSupportedCurrenciesResponse.SerializeToString,
),
'Convert': grpc.unary_unary_rpc_method_handler(
servicer.Convert,
request_deserializer=demo__pb2.CurrencyConversionRequest.FromString,
response_serializer=demo__pb2.Money.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.CurrencyService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class CurrencyService(object):
"""-----------------Currency service-----------------
"""
@staticmethod
def GetSupportedCurrencies(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CurrencyService/GetSupportedCurrencies',
demo__pb2.Empty.SerializeToString,
demo__pb2.GetSupportedCurrenciesResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def Convert(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CurrencyService/Convert',
demo__pb2.CurrencyConversionRequest.SerializeToString,
demo__pb2.Money.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class PaymentServiceStub(object):
"""-------------Payment service-----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.Charge = channel.unary_unary(
'/hipstershop.PaymentService/Charge',
request_serializer=demo__pb2.ChargeRequest.SerializeToString,
response_deserializer=demo__pb2.ChargeResponse.FromString,
)
class PaymentServiceServicer(object):
"""-------------Payment service-----------------
"""
def Charge(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_PaymentServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'Charge': grpc.unary_unary_rpc_method_handler(
servicer.Charge,
request_deserializer=demo__pb2.ChargeRequest.FromString,
response_serializer=demo__pb2.ChargeResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.PaymentService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class PaymentService(object):
"""-------------Payment service-----------------
"""
@staticmethod
def Charge(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.PaymentService/Charge',
demo__pb2.ChargeRequest.SerializeToString,
demo__pb2.ChargeResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class EmailServiceStub(object):
"""-------------Email service-----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.SendOrderConfirmation = channel.unary_unary(
'/hipstershop.EmailService/SendOrderConfirmation',
request_serializer=demo__pb2.SendOrderConfirmationRequest.SerializeToString,
response_deserializer=demo__pb2.Empty.FromString,
)
class EmailServiceServicer(object):
"""-------------Email service-----------------
"""
def SendOrderConfirmation(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_EmailServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'SendOrderConfirmation': grpc.unary_unary_rpc_method_handler(
servicer.SendOrderConfirmation,
request_deserializer=demo__pb2.SendOrderConfirmationRequest.FromString,
response_serializer=demo__pb2.Empty.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.EmailService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class EmailService(object):
"""-------------Email service-----------------
"""
@staticmethod
def SendOrderConfirmation(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.EmailService/SendOrderConfirmation',
demo__pb2.SendOrderConfirmationRequest.SerializeToString,
demo__pb2.Empty.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class CheckoutServiceStub(object):
"""-------------Checkout service-----------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.PlaceOrder = channel.unary_unary(
'/hipstershop.CheckoutService/PlaceOrder',
request_serializer=demo__pb2.PlaceOrderRequest.SerializeToString,
response_deserializer=demo__pb2.PlaceOrderResponse.FromString,
)
class CheckoutServiceServicer(object):
"""-------------Checkout service-----------------
"""
def PlaceOrder(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_CheckoutServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'PlaceOrder': grpc.unary_unary_rpc_method_handler(
servicer.PlaceOrder,
request_deserializer=demo__pb2.PlaceOrderRequest.FromString,
response_serializer=demo__pb2.PlaceOrderResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.CheckoutService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class CheckoutService(object):
"""-------------Checkout service-----------------
"""
@staticmethod
def PlaceOrder(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.CheckoutService/PlaceOrder',
demo__pb2.PlaceOrderRequest.SerializeToString,
demo__pb2.PlaceOrderResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
class AdServiceStub(object):
"""------------Ad service------------------
"""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.GetAds = channel.unary_unary(
'/hipstershop.AdService/GetAds',
request_serializer=demo__pb2.AdRequest.SerializeToString,
response_deserializer=demo__pb2.AdResponse.FromString,
)
class AdServiceServicer(object):
"""------------Ad service------------------
"""
def GetAds(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_AdServiceServicer_to_server(servicer, server):
rpc_method_handlers = {
'GetAds': grpc.unary_unary_rpc_method_handler(
servicer.GetAds,
request_deserializer=demo__pb2.AdRequest.FromString,
response_serializer=demo__pb2.AdResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'hipstershop.AdService', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class AdService(object):
"""------------Ad service------------------
"""
@staticmethod
def GetAds(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/hipstershop.AdService/GetAds',
demo__pb2.AdRequest.SerializeToString,
demo__pb2.AdResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

View File

@@ -0,0 +1,26 @@
#!/bin/bash -eu
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# [START gke_recommendationservice_genproto]
# script to compile python protos
#
# requires gRPC tools:
# pip install -r requirements.txt
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/demo.proto
# [END gke_recommendationservice_genproto]

View File

@@ -0,0 +1,41 @@
#!/usr/bin/python
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import sys
from pythonjsonlogger import jsonlogger
# TODO(yoshifumi) this class is duplicated since other Python services are
# not sharing the modules for logging.
class CustomJsonFormatter(jsonlogger.JsonFormatter):
def add_fields(self, log_record, record, message_dict):
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
if not log_record.get('timestamp'):
log_record['timestamp'] = record.created
if log_record.get('severity'):
log_record['severity'] = log_record['severity'].upper()
else:
log_record['severity'] = record.levelname
def getJSONLogger(name):
logger = logging.getLogger(name)
handler = logging.StreamHandler(sys.stdout)
formatter = CustomJsonFormatter('%(timestamp)s %(severity)s %(name)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.propagate = False
return logger

View File

@@ -0,0 +1,156 @@
#!/usr/bin/python
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import random
import time
import traceback
from concurrent import futures
# @TODO: Temporarily removed in https://github.com/GoogleCloudPlatform/microservices-demo/pull/3196
# import googlecloudprofiler
from google.auth.exceptions import DefaultCredentialsError
import grpc
import demo_pb2
import demo_pb2_grpc
from grpc_health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc
from opentelemetry import trace
from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient, GrpcInstrumentorServer
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from logger import getJSONLogger
logger = getJSONLogger('recommendationservice-server')
def initStackdriverProfiling():
project_id = None
try:
project_id = os.environ["GCP_PROJECT_ID"]
except KeyError:
# Environment variable not set
pass
# @TODO: Temporarily removed in https://github.com/GoogleCloudPlatform/microservices-demo/pull/3196
# for retry in range(1,4):
# try:
# if project_id:
# googlecloudprofiler.start(service='recommendation_server', service_version='1.0.0', verbose=0, project_id=project_id)
# else:
# googlecloudprofiler.start(service='recommendation_server', service_version='1.0.0', verbose=0)
# logger.info("Successfully started Stackdriver Profiler.")
# return
# except (BaseException) as exc:
# logger.info("Unable to start Stackdriver Profiler Python agent. " + str(exc))
# if (retry < 4):
# logger.info("Sleeping %d seconds to retry Stackdriver Profiler agent initialization"%(retry*10))
# time.sleep (1)
# else:
# logger.warning("Could not initialize Stackdriver Profiler after retrying, giving up")
return
class RecommendationService(demo_pb2_grpc.RecommendationServiceServicer):
def ListRecommendations(self, request, context):
max_responses = 5
# fetch list of products from product catalog stub
cat_response = product_catalog_stub.ListProducts(demo_pb2.Empty())
product_ids = [x.id for x in cat_response.products]
filtered_products = list(set(product_ids)-set(request.product_ids))
num_products = len(filtered_products)
num_return = min(max_responses, num_products)
# sample list of indicies to return
indices = random.sample(range(num_products), num_return)
# fetch product ids from indices
prod_list = [filtered_products[i] for i in indices]
logger.info("[Recv ListRecommendations] product_ids={}".format(prod_list))
# build and return response
response = demo_pb2.ListRecommendationsResponse()
response.product_ids.extend(prod_list)
return response
def Check(self, request, context):
return health_pb2.HealthCheckResponse(
status=health_pb2.HealthCheckResponse.SERVING)
def Watch(self, request, context):
return health_pb2.HealthCheckResponse(
status=health_pb2.HealthCheckResponse.UNIMPLEMENTED)
if __name__ == "__main__":
logger.info("initializing recommendationservice")
try:
if "DISABLE_PROFILER" in os.environ:
raise KeyError()
else:
logger.info("Profiler enabled.")
initStackdriverProfiling()
except KeyError:
logger.info("Profiler disabled.")
try:
grpc_client_instrumentor = GrpcInstrumentorClient()
grpc_client_instrumentor.instrument()
grpc_server_instrumentor = GrpcInstrumentorServer()
grpc_server_instrumentor.instrument()
if os.environ["ENABLE_TRACING"] == "1":
trace.set_tracer_provider(TracerProvider())
otel_endpoint = os.getenv("COLLECTOR_SERVICE_ADDR", "localhost:4317")
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint = otel_endpoint,
insecure = True
)
)
)
except (KeyError, DefaultCredentialsError):
logger.info("Tracing disabled.")
except Exception as e:
logger.warn(f"Exception on Cloud Trace setup: {traceback.format_exc()}, tracing disabled.")
port = os.environ.get('PORT', "8080")
catalog_addr = os.environ.get('PRODUCT_CATALOG_SERVICE_ADDR', '')
if catalog_addr == "":
raise Exception('PRODUCT_CATALOG_SERVICE_ADDR environment variable not set')
logger.info("product catalog address: " + catalog_addr)
channel = grpc.insecure_channel(catalog_addr)
product_catalog_stub = demo_pb2_grpc.ProductCatalogServiceStub(channel)
# create gRPC server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# add class to gRPC server
service = RecommendationService()
demo_pb2_grpc.add_RecommendationServiceServicer_to_server(service, server)
health_pb2_grpc.add_HealthServicer_to_server(service, server)
# start server
logger.info("listening on port: " + port)
server.add_insecure_port('[::]:'+port)
server.start()
# keep alive
try:
while True:
time.sleep(10000)
except KeyboardInterrupt:
server.stop(0)

View File

@@ -0,0 +1,8 @@
google-api-core==2.28.1
grpcio-health-checking==1.76.0
python-json-logger==4.0.0
requests==2.32.5
rsa==4.9.1
opentelemetry-distro==0.60b1
opentelemetry-instrumentation-grpc==0.60b1
opentelemetry-exporter-otlp-proto-grpc==1.39.1

View File

@@ -0,0 +1,101 @@
# This file was autogenerated by uv via the following command:
# uv pip compile requirements.in -o requirements.txt
cachetools==5.3.2
# via google-auth
certifi==2024.7.4
# via requests
charset-normalizer==3.3.2
# via requests
google-api-core==2.28.1
# via -r requirements.in
google-auth==2.23.4
# via google-api-core
googleapis-common-protos==1.72.0
# via
# google-api-core
# opentelemetry-exporter-otlp-proto-grpc
grpcio==1.76.0
# via
# grpcio-health-checking
# opentelemetry-exporter-otlp-proto-grpc
grpcio-health-checking==1.76.0
# via -r requirements.in
idna==3.7
# via requests
importlib-metadata==6.8.0
# via opentelemetry-api
opentelemetry-api==1.39.1
# via
# opentelemetry-distro
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-instrumentation
# opentelemetry-instrumentation-grpc
# opentelemetry-sdk
# opentelemetry-semantic-conventions
opentelemetry-distro==0.60b1
# via -r requirements.in
opentelemetry-exporter-otlp-proto-common==1.39.1
# via opentelemetry-exporter-otlp-proto-grpc
opentelemetry-exporter-otlp-proto-grpc==1.39.1
# via -r requirements.in
opentelemetry-instrumentation==0.60b1
# via
# opentelemetry-distro
# opentelemetry-instrumentation-grpc
opentelemetry-instrumentation-grpc==0.60b1
# via -r requirements.in
opentelemetry-proto==1.39.1
# via
# opentelemetry-exporter-otlp-proto-common
# opentelemetry-exporter-otlp-proto-grpc
opentelemetry-sdk==1.39.1
# via
# opentelemetry-distro
# opentelemetry-exporter-otlp-proto-grpc
opentelemetry-semantic-conventions==0.60b1
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-grpc
# opentelemetry-sdk
packaging==25.0
# via opentelemetry-instrumentation
proto-plus==1.27.0
# via google-api-core
protobuf==6.33.5
# via
# google-api-core
# googleapis-common-protos
# grpcio-health-checking
# opentelemetry-proto
# proto-plus
pyasn1==0.5.0
# via
# pyasn1-modules
# rsa
pyasn1-modules==0.3.0
# via google-auth
python-json-logger==4.0.0
# via -r requirements.in
requests==2.32.5
# via
# -r requirements.in
# google-api-core
rsa==4.9.1
# via
# -r requirements.in
# google-auth
typing-extensions==4.15.0
# via
# grpcio
# opentelemetry-api
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-sdk
# opentelemetry-semantic-conventions
urllib3==2.6.3
# via requests
wrapt==1.16.0
# via
# opentelemetry-instrumentation
# opentelemetry-instrumentation-grpc
zipp==3.19.1
# via importlib-metadata