def run(self): try: for response in self._watch_response_iterator: if response.created: self._watch_id_callbacks[response.watch_id] = \ self._callback self._watch_id_queue.put(response.watch_id) callback = self._watch_id_callbacks.get(response.watch_id) if callback: # The watcher can be safely reused, but adding a new event # to indicate that the revision is already compacted # requires api change which would break all users of this # module. So, raising an exception if a watcher is still # alive. The caller has to create a new client instance to # recover would break all users of this module. if response.compact_revision != 0: callback(etcd3_exceptions.RevisionCompactedError( response.compact_revision)) self.cancel(response.watch_id) continue for event in response.events: callback(events.new_event(event)) except grpc.RpcError as e: self.stop() if self._watch_id_callbacks: for callback in self._watch_id_callbacks.values(): callback(e)
def _handle_response(self, rs): with self._lock: if rs.created: if not rs.canceled: # If the new watch request has already expired then cancel the # created watch right away. if not self._new_watch: self._cancel_no_lock(rs.watch_id) return if rs.compact_revision != 0: self._new_watch.err = exceptions.RevisionCompactedError( rs.compact_revision) return self._callbacks[rs.watch_id] = self._new_watch.callback self._new_watch.id = rs.watch_id self._new_watch_cond.notify_all() elif rs.cancel_reason: rpc_error = grpc.RpcError() rpc_error.code = lambda: grpc.StatusCode.CANCELLED rpc_error.message = rs.cancel_reason raise rpc_error callback = self._callbacks.get(rs.watch_id) # Ignore leftovers from canceled watches. if not callback: return # The watcher can be safely reused, but adding a new event # to indicate that the revision is already compacted # requires api change which would break all users of this # module. So, raising an exception if a watcher is still # alive. if rs.compact_revision != 0: err = exceptions.RevisionCompactedError(rs.compact_revision) _safe_callback(callback, err) self.cancel(rs.watch_id) return # Call the callback even when there are no events in the watch # response so as not to ignore progress notify responses. if rs.events or not (rs.created or rs.canceled): new_events = [events.new_event(event) for event in rs.events] response = WatchResponse(rs.header, new_events) _safe_callback(callback, response)
def _handle_response(self, rs): with self._lock: if rs.created: # If the new watch request has already expired then cancel the # created watch right away. if not self._new_watch: self._cancel_no_lock(rs.watch_id) return if rs.compact_revision != 0: self._new_watch.err = exceptions.RevisionCompactedError( rs.compact_revision) return self._callbacks[rs.watch_id] = self._new_watch.callback self._new_watch.id = rs.watch_id self._new_watch_cond.notify_all() callback = self._callbacks.get(rs.watch_id) # Ignore leftovers from canceled watches. if not callback: return # The watcher can be safely reused, but adding a new event # to indicate that the revision is already compacted # requires api change which would break all users of this # module. So, raising an exception if a watcher is still # alive. if rs.compact_revision != 0: err = exceptions.RevisionCompactedError(rs.compact_revision) _safe_callback(callback, err) self.cancel(rs.watch_id) return for event in rs.events: _safe_callback(callback, events.new_event(event))