0

I am using python v3.5 with the package spyne 2.13 running on a gunicorn server v19.9

I wrote a small SOAP Webservice with python spyne (working well). It takes a string and enqueues it to rabbitmq. It must not neccessarily be rabbitmq, but also a simple DB insert oslt. Right now it works fine, but each time the webservice is called, it

  • opens a rabbitmq connection (or a DB connection if you'd like)
  • sends the message
  • closes the connection again(?)

I'd like to somehow preserve the connection in some sort of 'instance variable' and re-use it everytime the Webservice gets called. So that it connects only once and not everytime i call the ws. Unfortunately spyne does not seem to create any objects, so there are no instance variables.

Generally: How can I preserve a state (DB or RabbitMQ Connection) when using spyne?

Sauer
  • 1,429
  • 4
  • 17
  • 32

1 Answers1

0

So I tried this Trick with static class properties like so:

class Ws2RabbitMQ(ServiceBase):

    rabbit_connection = pika.BlockingConnection(
        pika.ConnectionParameters(host='localhost'))
    rabbit_channel = rabbit_connection.channel()

    @staticmethod
    def connectRabbit():
        rabbit_cred = pika.PlainCredentials(username='...', password='...')
        Ws2RabbitMQ.rabbit_connection = pika.BlockingConnection(pika.ConnectionParameters(
            host='...', virtual_host='...', credentials=rabbit_cred))
        Ws2RabbitMQ.rabbit_channel = Ws2RabbitMQ.rabbit_connection.channel()
        print('Rabbit connected!')

    @rpc(AnyXml, _returns=Unicode)
    def exportGRID(ctx, payload):
        try:
            if not Ws2RabbitMQ.rabbit_connection.is_open:
                print('RabbitMQ Connection lost - reconnecting...')
                Ws2RabbitMQ.connectRabbit()
        except Exception as e:
            print('RabbitMQ Connection not found - initiating...')
            Ws2RabbitMQ.connectRabbit()

        Ws2RabbitMQ.rabbit_channel.basic_publish(
            exchange='ws2rabbitmq', routing_key="blind", body=payload)

        print(" [x] Sent")
        return 'OK'

When I call the webservice twice, it works. Now, the Connection is created only once and kept in the Singleton Property.

Here is the scripts output:

RabbitMQ Connection not found - initiating...
Rabbit connected!
 [x] Sent
 [x] Sent
Sauer
  • 1,429
  • 4
  • 17
  • 32
  • Btw: I forgot to say, that my webservice resides behind a haproxy. For whatever reason, the property pika connection.is_open does not work properly. When rabbit closes the connection, pika still returns true here. When connected directly to rabbitmq (without haproxy) it works fine. Seems to be a known issue, but -> I dont care :) – Sauer Aug 27 '19 at 06:41
  • Maintaining a connection pool is generally the job of high-level client libraries. See eg. txpostgres. Note that library-provided connection pools don't look much different than your solution. You might need to take precautions against race conditions that might leave you with two open connections instead of one, and maybe move the code in the try/except block into another function, but that's about it. – Burak Arslan Aug 27 '19 at 21:30
  • 1
    Also note that ``ctx.service_class`` gives you access to the service class. – Burak Arslan Aug 27 '19 at 21:30