示例#1
0
    def __init__(self, url):
        self.url = url

        # add callbacks to these to learn if we failed to connect
        # (approximately) or if the ccnnection was unexpectedly lost
        self.connectionFailed = defer.Deferred()
        self.connectionLost = defer.Deferred()

        self._listeners = set()
        log.info("start read from %s", url)
        # note: fullGraphReceived isn't guaranteed- the stream could
        # start with patches
        self._fullGraphReceived = False
        self._eventSource = EventSource(url.toPython().encode("utf8"))
        self._eventSource.protocol.delimiter = "\n"

        self._eventSource.addEventListener("fullGraph", self._onFullGraph)
        self._eventSource.addEventListener("patch", self._onPatch)
        self._eventSource.onerror(self._onError)

        origSet = self._eventSource.protocol.setFinishedDeferred

        def sfd(d):
            origSet(d)
            d.addCallback(self._onDisconnect)

        self._eventSource.protocol.setFinishedDeferred = sfd
示例#2
0
class PatchSource(object):
    """wrap EventSource so it emits Patch objects and has an explicit stop method."""

    def __init__(self, url):
        self.url = url

        # add callbacks to these to learn if we failed to connect
        # (approximately) or if the ccnnection was unexpectedly lost
        self.connectionFailed = defer.Deferred()
        self.connectionLost = defer.Deferred()

        self._listeners = set()
        log.info("start read from %s", url)
        # note: fullGraphReceived isn't guaranteed- the stream could
        # start with patches
        self._fullGraphReceived = False
        self._eventSource = EventSource(url.toPython().encode("utf8"))
        self._eventSource.protocol.delimiter = "\n"

        self._eventSource.addEventListener("fullGraph", self._onFullGraph)
        self._eventSource.addEventListener("patch", self._onPatch)
        self._eventSource.onerror(self._onError)

        origSet = self._eventSource.protocol.setFinishedDeferred

        def sfd(d):
            origSet(d)
            d.addCallback(self._onDisconnect)

        self._eventSource.protocol.setFinishedDeferred = sfd

    def stats(self):
        return {"url": self.url, "fullGraphReceived": self._fullGraphReceived}

    def addPatchListener(self, func):
        """
        func(patch, fullGraph=[true if the patch is the initial fullgraph])
        """
        self._listeners.add(func)

    def stop(self):
        log.info("stop read from %s", self.url)
        try:
            self._eventSource.protocol.stopProducing()  # needed?
        except AttributeError:
            pass
        self._eventSource = None

    def _onDisconnect(self, a):
        log.debug("PatchSource._onDisconnect from %s", self.url)
        # skip this if we're doing a stop?
        self.connectionLost.callback(None)

    def _onError(self, msg):
        log.debug("PatchSource._onError from %s %r", self.url, msg)
        if not self._fullGraphReceived:
            self.connectionFailed.callback(msg)
        else:
            self.connectionLost.callback(msg)

    def _onFullGraph(self, message):
        try:
            g = ConjunctiveGraph()
            g.parse(StringInputSource(message), format="json-ld")
            p = Patch(addGraph=g)
            self._sendPatch(p, fullGraph=True)
        except:
            log.error(traceback.format_exc())
            raise
        self._fullGraphReceived = True

    def _onPatch(self, message):
        try:
            p = patchFromJson(message)
            self._sendPatch(p, fullGraph=False)
        except:
            log.error(traceback.format_exc())
            raise

    def _sendPatch(self, p, fullGraph):
        log.debug("PatchSource %s received patch %s (fullGraph=%s)", self.url, p.shortSummary(), fullGraph)
        for lis in self._listeners:
            lis(p, fullGraph=fullGraph)

    def __del__(self):
        if self._eventSource:
            raise ValueError