async def query(self, data):
        """Query events

        Args:
            data (common.QueryData): query data

        Returns:
            List[common.Event]

        """
        backend_data = common.BackendQueryData(
            event_ids=data.event_ids,
            event_type_ids=(self._query_types_to_ids(data.event_types)
                            if data.event_types is not None else None),
            t_from=data.t_from,
            t_to=data.t_to,
            source_t_from=data.source_t_from,
            source_t_to=data.source_t_to,
            payload=data.payload,
            order=data.order,
            order_by=data.order_by,
            unique_type=data.unique_type,
            max_results=data.max_results)
        events = await self._backend.query(backend_data)

        return [common.Event(
            event_id=event.event_id,
            event_type=self._event_type_from_id(event.event_type_id),
            timestamp=event.timestamp,
            source_timestamp=event.source_timestamp,
            payload=event.payload
        ) for event in events]
    async def register(self, events):
        """Register events

        Args:
            events (List[common.ProcessEvent]): process events

        Returns:
            List[Optional[common.Event]]

        """
        now = common.now()

        backend_events = [common.BackendEvent(
            event_id=event.event_id,
            event_type_id=self._get_event_type_id(event.event_type),
            timestamp=now,
            source_timestamp=event.source_timestamp,
            payload=event.payload
        ) for event in events]

        if self._new_mappings:
            await self._backend.add_event_type_id_mappings(self._new_mappings)
            self._new_mappings = {}
        await self._backend.register(backend_events)

        return [common.Event(
            event_id=event.event_id,
            event_type=event.event_type,
            timestamp=now,
            source_timestamp=event.source_timestamp,
            payload=event.payload
        ) for event in events]
Example #3
0
 def register_cb(source, events):
     register_queue.put_nowait(events)
     process_events = [
         engine.create_process_event(source, event) for event in events
     ]
     return [
         common.Event(event_id=i.event_id,
                      event_type=i.event_type,
                      timestamp=common.now(),
                      source_timestamp=i.source_timestamp,
                      payload=i.payload) for i in process_events
     ]
Example #4
0
 async def register(self, process_events):
     if not self._register_cb:
         now = common.now()
         return [
             common.Event(event_id=process_event.event_id,
                          event_type=process_event.event_type,
                          timestamp=now,
                          source_timestamp=process_event.source_timestamp,
                          payload=process_event.payload)
             for process_event in process_events
         ]
     return self._register_cb(process_events)
Example #5
0
 async def register(
     self, process_events: typing.List[common.ProcessEvent]
 ) -> typing.List[typing.Optional[common.Event]]:
     """Register events"""
     now = common.now()
     events = [
         common.Event(event_id=process_event.event_id,
                      event_type=process_event.event_type,
                      timestamp=now,
                      source_timestamp=process_event.source_timestamp,
                      payload=process_event.payload)
         for process_event in process_events
     ]
     return await self._backend.register(events)
Example #6
0
async def test_query(backend_module_name, create_backend_module):
    conf = {'server_id': 123, 'backend': {'module': backend_module_name}}
    event_ids = [common.EventId(conf['server_id'], i) for i in range(10)]
    events = [
        common.Event(event_id=event_id,
                     event_type=[],
                     timestamp=common.now(),
                     source_timestamp=None,
                     payload=None) for event_id in event_ids
    ]
    query_data = common.QueryData()

    def query(data):
        assert query_data == data
        return events

    with create_backend_module(query_cb=query):
        engine = await hat.event.server.backend_engine.create(conf)

        result = await engine.query(query_data)
        assert result == events

        await engine.async_close()
Example #7
0
async def test_query():
    query_data = common.QueryData()
    events = [
        common.Event(event_id=common.EventId(1, i),
                     event_type=(),
                     timestamp=common.now(),
                     source_timestamp=None,
                     payload=None) for i in range(10)
    ]

    def on_query(data):
        assert data == query_data
        return events

    conf = {'modules': []}
    backend = BackendEngine(query_cb=on_query)
    engine = await hat.event.server.module_engine.create(conf, backend)

    result = await engine.query(query_data)
    assert result == events

    await engine.async_close()
    await backend.async_close()
Example #8
0
    async def query(self, data):
        """See :meth:`common.Backend.query`"""
        conditions = []
        event_type_id_condition = None
        params = {}

        if data.max_results is not None and data.max_results <= 0:
            return []
        if data.event_ids is not None:
            if not data.event_ids:
                return []
            subconditions = []
            for i, event_id in enumerate(data.event_ids):
                server_label = f'server_id_{i}'
                instance_label = f'instance_id_{i}'
                params[server_label] = event_id.server
                params[instance_label] = event_id.instance
                subconditions.append(f"(server_id = :{server_label} AND "
                                     f"instance_id = :{instance_label})")
            conditions.append(f"({' OR '.join(subconditions)})")
        if data.event_types is not None:
            event_type_ids = self._event_type_registry.query_identifiers(
                data.event_types)
            if not event_type_ids:
                return []
            labels = []
            for i, event_type_id in enumerate(event_type_ids):
                label = f'event_type_id_{i}'
                params[label] = event_type_id
                labels.append(label)
            event_type_id_condition = ("event_type_id IN (" +
                                       ', '.join(f":{label}"
                                                 for label in labels) + ")")
        if data.t_from is not None:
            conditions.append("timestamp >= :t_from")
            params['t_from'] = common.timestamp_to_bytes(data.t_from)
        if data.t_to is not None:
            conditions.append("timestamp <= :t_to")
            params['t_to'] = common.timestamp_to_bytes(data.t_to)
        if data.source_t_from is not None:
            conditions.append("source_timestamp >= :source_t_from")
            params['source_t_from'] = common.timestamp_to_bytes(
                data.source_t_from)
        if data.source_t_to is not None:
            conditions.append("source_timestamp <= :source_t_to")
            params['source_t_to'] = common.timestamp_to_bytes(data.source_t_to)
        if data.payload is not None:
            conditions.append("payload = :payload")
            params['payload'] = self._encode_payload(data.payload)

        order_cols = {
            common.OrderBy.TIMESTAMP: ('timestamp', 'source_timestamp'),
            common.OrderBy.SOURCE_TIMESTAMP: ('source_timestamp', 'timestamp')
        }[data.order_by]
        order_by = {
            common.Order.ASCENDING: " ASC NULLS LAST",
            common.Order.DESCENDING: " DESC NULLS LAST"
        }
        ordering_term = (f"{order_cols[0]} {order_by[data.order]}, "
                         f"{order_cols[1]} DESC NULLS LAST")

        if data.unique_type:
            key_columns = ['server_id', 'instance_id']
            # uglier, but much, much faster than PARTITION BY if
            # len(mappings) << len(events) because with this query
            # proper indexes are used
            sql = ("SELECT e.* FROM events AS e JOIN (SELECT " + ", ".join(
                f"(SELECT {column} FROM events " +
                " WHERE event_type_id = m.event_type_id" +
                (" AND " + " AND ".join(conditions) if conditions else "") +
                f" ORDER BY {ordering_term} LIMIT 1) AS t_{column}"
                for column in key_columns) + " FROM mappings m" +
                   (f" WHERE {event_type_id_condition}"
                    if event_type_id_condition else "") + ") ON " +
                   " AND ".join(f"e.{column} = t_{column}"
                                for column in key_columns) +
                   f" ORDER BY {ordering_term}" +
                   (f" LIMIT {data.max_results}" if data.max_results else ""))
        else:
            if event_type_id_condition:
                conditions.append(event_type_id_condition)
            sql = (
                "SELECT * FROM events" +
                (" WHERE " + " AND ".join(conditions) if conditions else "") +
                f" ORDER BY {ordering_term}" +
                (f" LIMIT {data.max_results}" if data.max_results else ""))

        async with self._query_pool.acquire() as conn:
            result = await conn.execute(sql, params)

        return [
            common.Event(
                event_id=common.EventId(server=row[0], instance=row[1]),
                event_type=self._event_type_registry.get_event_type(row[2]),
                timestamp=common.timestamp_from_bytes(row[3]),
                source_timestamp=(common.timestamp_from_bytes(row[4])
                                  if row[4] is not None else None),
                payload=(self._decode_payload(row[5])
                         if row[5] is not None else None)) for row in result
        ]
Example #9
0
    for _ in range(10):
        now_dt = common.timestamp_to_datetime(common.now())
        delta = datetime.datetime.now(datetime.timezone.utc) - now_dt

        assert delta < datetime.timedelta(seconds=1)
        if previous_dt is not None:
            assert now_dt >= previous_dt

        previous_dt = now_dt


@pytest.mark.parametrize("event", [
    common.Event(
        event_id=common.EventId(0, 0),
        event_type=('a',),
        timestamp=common.now(),
        source_timestamp=None,
        payload=None),

    common.Event(
        event_id=common.EventId(0, 0),
        event_type=('a',),
        timestamp=common.now(),
        source_timestamp=common.now(),
        payload=common.EventPayload(
            type=common.EventPayloadType.BINARY,
            data=b'123')),

    common.Event(
        event_id=common.EventId(123, 456),
        event_type=('a', 'b', 'c'),