def heartbeat(self, bucket_id: str, event: Event, pulsetime: float, queued: bool=False, commit_interval: Optional[float]=None) -> Optional[Event]: from aw_transform.heartbeats import heartbeat_merge endpoint = "buckets/{}/heartbeat?pulsetime={}".format(bucket_id, pulsetime) commit_interval = commit_interval if commit_interval else self.commit_interval if queued: if bucket_id not in self.last_heartbeat: self.last_heartbeat[bucket_id] = event return None last_heartbeat = self.last_heartbeat[bucket_id] merge = heartbeat_merge(last_heartbeat, event, pulsetime) if merge: # If last_heartbeat becomes longer than commit_interval # then commit, else cache merged. diff = (last_heartbeat.duration).total_seconds() if diff > commit_interval: data = merge.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event else: self.last_heartbeat[bucket_id] = merge else: data = last_heartbeat.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event return None else: return Event(**self._post(endpoint, event.to_json_dict()).json())
def post(self, bucket_id): """ Where heartbeats are sent. """ logger.debug("Received post request for heartbeat in bucket '{}' and data: {}".format(bucket_id, request.get_json())) if bucket_id not in app.db.buckets(): # NOTE: This "create_bucket" arg is deprecated if "create_bucket" in request.args: # TODO: How should we pass type, client and hostname? As args? Arg for createbucket could be a JSON object (it would be short). app.db.create_bucket( bucket_id, type='unspecified', # data["type"], client='unknown', # data["client"], hostname='unknown', # data["hostname"], created=datetime.now() ) else: msg = "There's no bucket named {}".format(bucket_id) raise BadRequest("NoSuchBucket", msg) if "pulsetime" not in request.args: raise BadRequest("MissingParameter", "Missing required parameter pulsetime") data = request.get_json() pulsetime = float(request.args["pulsetime"]) if not isinstance(data, dict): logger.error("Invalid JSON object") raise BadRequest("InvalidJSON", "Invalid JSON object") heartbeat = Event(**data) events = app.db[bucket_id].get(limit=3) # FIXME: The below is needed due to the weird fact that for some reason # events[0] turns out to be the *oldest* event, # events[1] turns out to be the latest, # events[2] the second latest, etc. events = sorted(events, key=lambda e: e.timestamp, reverse=True) # Uncomment this to verify my above claim: # for e in events: # print(e.timestamp) # print(e.labels) if len(events) >= 1: last_event = events[0] merged = transforms.heartbeat_merge(last_event, heartbeat, pulsetime) if merged is not None: # Heartbeat was merged into last_event app.db[bucket_id].replace_last(merged) return merged.to_json_dict(), 200 # Heartbeat should be stored as new event logger.debug("last event either didn't have identical labels, was too old or didn't exist. heartbeat will be stored as new event") app.db[bucket_id].insert(heartbeat) return heartbeat.to_json_dict(), 200
def heartbeat( self, bucket_id: str, event: Event, pulsetime: float, queued: bool = False, commit_interval: Optional[float] = None, ) -> Optional[Event]: """ Args: bucket_id: The bucket_id of the bucket to send the heartbeat to event: The actual heartbeat event pulsetime: The maximum amount of time in seconds since the last heartbeat to be merged with the previous heartbeat in aw-server queued: Use the aw-client queue feature to queue events if client loses connection with the server commit_interval: Override default pre-merge commit interval NOTE: This endpoint can use the failed requests retry queue. This makes the request itself non-blocking and therefore the function will in that case always returns None. """ from aw_transform.heartbeats import heartbeat_merge endpoint = "buckets/{}/heartbeat?pulsetime={}".format(bucket_id, pulsetime) commit_interval = ( commit_interval if commit_interval != None else self.commit_interval ) if queued: # Pre-merge heartbeats if bucket_id not in self.last_heartbeat: self.last_heartbeat[bucket_id] = event return None last_heartbeat = self.last_heartbeat[bucket_id] merge = heartbeat_merge(last_heartbeat, event, pulsetime) if merge: # If last_heartbeat becomes longer than commit_interval # then commit, else cache merged. diff = (last_heartbeat.duration).total_seconds() if diff >= commit_interval: data = merge.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event else: self.last_heartbeat[bucket_id] = merge else: data = last_heartbeat.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event return None else: return Event(**self._post(endpoint, event.to_json_dict()).json())
def heartbeat(self, bucket_id: str, event: Event, pulsetime: float, queued: bool=False, commit_interval: Optional[float]=None) -> Optional[Event]: """ Args: bucket_id: The bucket_id of the bucket to send the heartbeat to event: The actual heartbeat event pulsetime: The maximum amount of time in seconds since the last heartbeat to be merged with the previous heartbeat in aw-server queued: Use the aw-client queue feature to queue events if client loses connection with the server commit_interval: Override default pre-merge commit interval NOTE: This endpoint can use the failed requests retry queue. This makes the request itself non-blocking and therefore the function will in that case always returns None. """ from aw_transform.heartbeats import heartbeat_merge endpoint = "buckets/{}/heartbeat?pulsetime={}".format(bucket_id, pulsetime) commit_interval = commit_interval if commit_interval else self.commit_interval if queued: # Pre-merge heartbeats if bucket_id not in self.last_heartbeat: self.last_heartbeat[bucket_id] = event return None last_heartbeat = self.last_heartbeat[bucket_id] merge = heartbeat_merge(last_heartbeat, event, pulsetime) if merge: # If last_heartbeat becomes longer than commit_interval # then commit, else cache merged. diff = (last_heartbeat.duration).total_seconds() if diff > commit_interval: data = merge.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event else: self.last_heartbeat[bucket_id] = merge else: data = last_heartbeat.to_json_dict() self.request_queue.add_request(endpoint, data) self.last_heartbeat[bucket_id] = event return None else: return Event(**self._post(endpoint, event.to_json_dict()).json())
def insert_event(self, bucket_id: str, event: Event) -> Event: endpoint = "buckets/{}/events".format(bucket_id) data = event.to_json_dict() return Event(**self._post(endpoint, data).json())
def test_event(self): event = Event(timestamp=valid_timestamp, data={"label": "test"}) self.validate(event.to_json_dict())
def insert_event(self, bucket_id: str, event: Event) -> None: endpoint = f"buckets/{bucket_id}/events" data = [event.to_json_dict()] self._post(endpoint, data)
def insert_event(self, bucket_id: str, event: Event) -> None: endpoint = "buckets/{}/events".format(bucket_id) data = [event.to_json_dict()] self._post(endpoint, data)