code: def notify(self, data):
          
          LOG.debug('notify received: %s', data)
          self._notify_count += 1
          if self._cancelled:
              LOG.debug('notify skipping due to `cancelled`')
              return self
          if self._once_done and self._once:
              LOG.debug('notify skipping due to `once`')
              return self
          with self._lock:
              try:
                  # notify next consumer immediately
                  self._waitables.get_nowait().put_nowait(data)
                  LOG.debug('found a consumer, notifying')
              except queue.Empty:
                  # store the notification
                  try:
                      self._notifications.put_nowait(data)
                      LOG.debug('no consumers, queueing data')
                  except queue.Full:
                      LOG.warning('notification queue full - discarding new data')
  
          # callbacks are sent straight away
          # bombproofing should be handled by individual callbacks
          for callback in self._callbacks:
              LOG.debug('callback: %s', callback)
              callback(data)
          self._once_done = True
          return self
docs: Notify this observer that data has arrived