Cómo obtener una respuesta en la devolución de llamada de suscripción de Google Pubsub en un servidor Flask para el streaming.
Me gustaría tener un flujo a través de un punto final de Flask, pero los eventos se envían dentro de la devolución de llamada del suscriptor a un tema (Google Cloud PubSub). Consulta el código a continuación:
def a_stream():
topic_name = 'projects/{project_id}/topics/{topic}'.format(
project_id=os.getenv('GOOGLE_CLOUD_PROJECT'),
topic="topic",
)
subscription_name = 'projects/{project_id}/subscriptions/{sub}'.format(
project_id=os.getenv('GOOGLE_CLOUD_PROJECT'),
sub="topic",
)
def callback(message):
print("imprimir")
yield "reducir a la mitad"
message.ack()
with pubsub_v1.SubscriberClient() as subscriber:
try:
subscriber.create_subscription(
name=subscription_name, topic=topic_name)
except:
#no hacer nada ya que el tema existe
pasar
future = subscriber.subscribe(subscription_name, callback=callback)
future.result()
@orders_bp.route("/aStream", methods=['GET'])
def get_order_status():
return Response(stream_with_context(a_stream()),
mimetype="text/event-stream")
Si ejecuto el código tal como está, no sucede nada. Si elimino el “reducir a la mitad” en la devolución de llamada, entonces puedo ver la “impresión” en la consola. Parece que el problema tiene que ver con el retorno, ¿hay alguna manera fácil de solucionar esto?
davy.ai
Sí, el problema está en la función de “yielding”. Según la documentación de Flask, las respuestas de transmisión (
stream responses
) deben ser iterables de BYTES o TEXT. Sin embargo, la declaraciónyield
en la funcióncallback
está devolviendo un objeto de tipo string que no es ni una secuencia de bytes ni un objeto de texto.Para solucionar esto, puedes codificar el objeto string en bytes antes de devolverlo. Modifica la función
callback
para codificar el objeto string antes de usar elyield
, de esta manera:Al agregar
.encode('utf-8')
al string devuelto, se convertirá en un objeto de bytes que Flask puede transmitir.