def put(self, name): # Back compatibility with previous endpoint version params = request.json.get('params') or request.json params_keys = params.keys() for param in ['predictor', 'stream_in', 'stream_out']: if param not in params_keys: return abort(400, 'Please provide "{}"'.format(param)) if 'integration' not in params_keys and 'connection' not in params_keys: return abort( 400, "'integration' in case of local installation and 'connection' in case of cloud are required." ) if 'integration' in params_keys: integration = get_db_integration(params['integration'], request.company_id) if integration is None: return abort( 404, 'Integration "{}" doesn\'t exist'.format( params['integration'])) if integration['type'] not in STREAM_INTEGRATION_TYPES: return abort( 400, 'Integration "{}" is not of type [{}]'.format( params['integration'], '/'.join(STREAM_INTEGRATION_TYPES))) else: if 'type' not in params_keys: return abort(404, "'type' parameter is required in case of cloud.") if db.session.query(db.Stream).filter_by( company_id=request.company_id, name=name).first() is not None: return abort(404, 'Stream "{}" already exists'.format(name)) if db.session.query(db.Predictor).filter_by( company_id=request.company_id, name=params['predictor']).first() is None: return abort( 404, 'Predictor "{}" doesn\'t exist'.format(params['predictor'])) stream = db.Stream(company_id=request.company_id, name=name, integration=params.get('integration'), predictor=params['predictor'], stream_in=params['stream_in'], stream_out=params['stream_out'], anomaly_stream=params.get('anomaly_stream'), learning_stream=params.get('learning_stream'), type=params.get('type'), connection_info=params.get('connection')) session.add(stream) session.commit() return {'success': True}, 200
def _loop(self): log.info("INTEGRATION %s: starting", self.name) while not STOP_THREADS_EVENT.wait(1.0): if self._control_stream is not None: # Create or delete streams based on messages from control_stream for dct in self._control_stream.read(): if 'action' not in dct: log.error( 'INTEGRATION %s: no action value found in control record - %s', self.name, dct) else: if dct['action'] == 'create': for k in [ 'name', 'predictor', 'stream_in', 'stream_out' ]: if k not in dct: # Not all required parameters were provided (i.e. stream will not be created) # TODO: what's a good way to notify user about this? log.error( 'INTEGRATION %s: stream creating error. not enough data in control record - %s', self.name, dct) break else: log.info('INTEGRATION %s: creating stream %s', self.name, dct['name']) if db.session.query(db.Stream).filter_by( name=dct['name'], company_id=self.company_id).first( ) is None: stream = db.Stream( company_id=self.company_id, name=dct['name'], integration=self.name, predictor=dct['predictor'], stream_in=dct['stream_in'], stream_out=dct['stream_out'], anomaly_stream=dct.get( 'stream_anomaly', None), learning_params=dct.get( 'learning_params', None), learning_threshold=dct.get( 'learning_threshold', None), ) db.session.add(stream) db.session.commit() else: log.error( 'INTEGRATION %s: stream with this name already exists - %s', self.name, dct['name']) elif dct['action'] == 'delete': for k in ['name']: if k not in dct: # Not all required parameters were provided (i.e. stream will not be created) # TODO: what's a good way to notify user about this? log.error( 'INTEGRATION %s: unable to delete stream - stream name is not provided', self.name) break else: log.error( 'INTEGRATION %s: deleting stream - %s', self.name, dct['name']) db.session.query(db.Stream).filter_by( company_id=self.company_id, integration=self.name, name=dct['name']).delete() db.session.commit() else: # Bad action value log.error( 'INTEGRATION %s: bad action value received - %s', self.name, dct) # it is really required to add 'commit' here # to avoid case when sessin.query returns previously # deleted object # https://stackoverflow.com/questions/10210080/how-to-disable-sqlalchemy-caching db.session.commit() stream_db_recs = db.session.query(db.Stream).filter_by( company_id=self.company_id, integration=self.name).all() # Stop streams that weren't found in DB indices_to_delete = [] for i, s in enumerate(self._streams): if s.name not in map(lambda x: x.name, stream_db_recs): log.info("INTEGRATION %s: stopping stream - %s", self.name, s.name) indices_to_delete.append(i) self._streams[i].stop_event.set() self._streams = [ s for i, s in enumerate(self._streams) if i not in indices_to_delete ] # Start new streams found in DB for s in stream_db_recs: if s.name not in map(lambda x: x.name, self._streams): log.info("INTEGRATION %s: starting stream - %s", self.name, s.name) self._streams.append(self._make_stream(s)) log.info("INTEGRATION %s: stopping", self.name) for s in self._streams: s.stop_event.set()