Python, suds - menangani cache dan respons WSDL yang busuk

Selama beberapa hari terakhir, kepalaku terbentur server SOAP yang bodoh.

Di log kesalahan saya, saya mendapatkan pengecualian/tracelog yang terlihat seperti ini: "Pengecualian: (Widget, Tidak Ada, ), harus qref" -- (frasa kuncinya adalah "harus qref").

Pertama, saya mengetahui bahwa kami memiliki cache yang busuk. Jadi saya menonaktifkan caching, namun masalah terus berlanjut.

Kedua, saya menemukan bahwa itu sebenarnya kesalahan server karena gagal memberi saya WSDL yang tepat, secara acak; terutama saat menggunakan beberapa instance pekerja. Sekilas berita - kontak operator server saya mengonfirmasi kesalahan "server terlalu sibuk" di lognya. "Wunderbar!" Rupanya, server mengalihkan ke halaman HTTP 200 padahal seharusnya menyediakan HTTP 503.

Saya bertanya-tanya bagaimana caranya agar lebih anggun dalam menangani perilaku buruk yang luar biasa ini, dan ternyata saya menemukan solusi yang berguna dan cukup umum. Posting di sini untuk referensi di masa mendatang.


person starlocke    schedule 08.05.2014    source sumber


Jawaban (1)


Sesuatu seperti ini:

from suds.client import Client
from suds.transport.https import HttpAuthenticated
from suds.xsd.doctor import ImportDoctor, Import
import os
import shutil
import time
from tempfile import gettempdir as tmp

class MyTransport(HttpAuthenticated):
    def __init__(self,*args,**kwargs):
        HttpAuthenticated.__init__(self,*args,**kwargs)
        self.last_headers = None
    def send(self,request):
        result = HttpAuthenticated.send(self,request)
        self.last_headers = result.headers
        return result

class TenaciousConnector():
    def init_client(self, wsdl_url):
        retries = 3
        services = None
        # Cached mode
        (client, services) = self._init_client(wsdl_url)
        while not services and retries > 0:
            nap_time = 6 - retries
            retries = retries - 1
            time.sleep(nap_time)
            # clear potentially rotten cache right before retrying
            shutil.rmtree(os.path.join(tmp(), 'suds'), True)
            (client, services) = self._init_client(wsdl_url)
        if not services:
            # No-cache mode
            retries = 3
            (client, services) = self._init_client(wsdl_url, False)
            while not services and retries > 0:
                nap_time = 6 - retries
                retries = retries - 1
                time.sleep(nap_time)
                (client, services) = self._init_client(wsdl_url, False)
        if not services:
            raise Exception("Failed at loading WSDL from {0}".format(wsdl_url))
        return client

    def _init_client(self, wsdl_url, cache=True):
        i_doc = ImportDoctor(Import('http://schemas.xmlsoap.org/soap/encoding/'))
        tx = MyTransport()
        if cache:
            client = Client(wsdl_url, doctor=i_doc, transport=tx)
        else:
            client = Client(wsdl_url, doctor=i_doc, transport=tx, cache=None)
        services = client.wsdl.services
        return (client, services)

Jenis yang digunakan seperti ini:

connector = TenaciousConnector()
client = connector.init_client("http://example.com/webservice/wsdl")
client.factory.create('Widget')
person starlocke    schedule 08.05.2014