Beispiel #1
0
async def run_test_until_event(flow,
                               core_client,
                               namespace,
                               endpoint,
                               stop_event,
                               logger,
                               sleep_time=0.05):
    # start port forwarding
    from jina.clients import Client

    gateway_pod_name = (core_client.list_namespaced_pod(
        namespace=namespace,
        label_selector='app=gateway').items[0].metadata.name)
    config_path = os.environ['KUBECONFIG']
    import portforward

    with portforward.forward(namespace, gateway_pod_name, flow.port, flow.port,
                             config_path):
        client_kwargs = dict(
            host='localhost',
            port=flow.port,
            return_responses=True,
            asyncio=True,
        )
        client_kwargs.update(flow._common_kwargs)

        client = Client(**client_kwargs)
        client.show_progress = True

        async def async_inputs(sent_ids: Set[int], sleep_time: float = 0.05):
            i = 0
            while True:
                sent_ids.add(i)
                yield Document(text=f'{i}')
                if stop_event.is_set():
                    logger.info(
                        f'stop yielding new requests after {i} requests')
                    return
                elif sleep_time:
                    await asyncio.sleep(sleep_time)
                i += 1

        responses = []
        sent_ids = set()
        async for resp in client.post(
                endpoint,
                inputs=functools.partial(async_inputs, sent_ids, sleep_time),
                request_size=1,
        ):
            responses.append(resp)

    logger.info(
        f'Client sent {len(sent_ids)} and received {(len(responses))} responses'
    )
    return responses, sent_ids
Beispiel #2
0
def client_send(client_id: int, port_in: int, protocol: str):
    from jina.clients import Client

    c = Client(protocol=protocol, port=port_in)

    # send requests
    return c.post(
        on='/',
        inputs=DocumentArray([Document(text=f'client{client_id}-Request')]),
        return_results=True,
    )
Beispiel #3
0
def test_disable_prefetch_fast_client_slow_executor(protocol, inputs,
                                                    monkeypatch,
                                                    simple_graph_dict_slow):
    monkeypatch.setattr(
        networking.GrpcConnectionPool,
        'send_requests_once',
        DummyMockConnectionPool.send_requests_once,
    )
    port_in = random_port()
    final_da = DocumentArray()
    p = multiprocessing.Process(
        target=create_runtime,
        kwargs={
            'protocol': protocol,
            'port_in': port_in,
            'graph_dict': simple_graph_dict_slow,
        },
    )
    p.start()
    time.sleep(1.0)
    client = Client(protocol=protocol, port=port_in)
    client.post(
        on='/',
        inputs=inputs,
        request_size=1,
        on_done=lambda response: on_done(response, final_da),
    )
    p.terminate()
    p.join()

    assert len(final_da) == INPUT_LEN
    # since Executor is slow, all client inputs should be read before 1st request exits from Executor.
    assert (
        final_da['id-0'].id < final_da['id-1'].id
    ), f'ids are not ordered with times {final_da["id-0"].tags["input_gen"]} and {final_da["id-1"].tags["input_gen"]}'
    assert (
        final_da['id-1'].id < final_da['id-2'].id
    ), f'ids are not ordered with times {final_da["id-1"].tags["input_gen"]} and {final_da["id-2"].tags["input_gen"]}'
    assert (
        final_da['id-2'].id < final_da['id-3'].id
    ), f'ids are not ordered with times {final_da["id-2"].tags["input_gen"]} and {final_da["id-3"].tags["input_gen"]}'
    assert final_da['id-0'].tags['input_gen'] < final_da['id-1'].tags[
        'input_gen']
    assert final_da['id-1'].tags['input_gen'] < final_da['id-2'].tags[
        'input_gen']
    assert final_da['id-2'].tags['input_gen'] < final_da['id-3'].tags[
        'input_gen']
    assert final_da['id-3'].tags['input_gen'] < final_da['id-0'].tags[
        'executor']
    # At least 1 request should reache `on_done` before all requests are processed in the Executor.
    # Validates that the requests are not pending at the Executor
    first_on_done_time = min(i.tags['on_done'] for i in final_da)
    last_executor_time = max(i.tags['executor'] for i in final_da)
    assert first_on_done_time < last_executor_time
Beispiel #4
0
def test_input_files(patterns, recursive, size, sampling_rate, read_mode):
    Client.check_input(
        _input_files(
            patterns=patterns,
            recursive=recursive,
            size=size,
            sampling_rate=sampling_rate,
            read_mode=read_mode,
        ),
        data_type=DataInputType.CONTENT,
    )
Beispiel #5
0
def test_disable_prefetch_slow_client_fast_executor(protocol, inputs,
                                                    monkeypatch,
                                                    simple_graph_dict_fast):
    monkeypatch.setattr(
        networking.GrpcConnectionPool,
        'send_requests_once',
        DummyMockConnectionPool.send_requests_once,
    )
    port_in = random_port()

    p = multiprocessing.Process(
        target=create_runtime,
        kwargs={
            'protocol': protocol,
            'port_in': port_in,
            'graph_dict': simple_graph_dict_fast,
        },
    )
    p.start()
    time.sleep(1.0)

    final_da = DocumentArray()

    client = Client(protocol=protocol, port=port_in)
    client.post(
        on='/',
        inputs=inputs,
        request_size=1,
        on_done=lambda response: on_done(response, final_da),
    )
    p.terminate()
    p.join()
    assert len(final_da) == INPUT_LEN
    # Since the input_gen is slow, order will always be gen -> exec -> on_done for every request
    assert final_da['id-0'].tags['input_gen'] < final_da['id-0'].tags[
        'executor']
    assert final_da['id-0'].tags['executor'] < final_da['id-0'].tags['on_done']
    assert final_da['id-0'].tags['on_done'] < final_da['id-1'].tags['input_gen']
    assert final_da['id-1'].tags['input_gen'] < final_da['id-1'].tags[
        'executor']
    assert final_da['id-1'].tags['executor'] < final_da['id-1'].tags['on_done']
    assert final_da['id-1'].tags['on_done'] < final_da['id-2'].tags['input_gen']
    assert final_da['id-2'].tags['input_gen'] < final_da['id-2'].tags[
        'executor']
    assert final_da['id-2'].tags['executor'] < final_da['id-2'].tags['on_done']
    assert final_da['id-2'].tags['on_done'] < final_da['id-3'].tags['input_gen']
    assert final_da['id-3'].tags['input_gen'] < final_da['id-3'].tags[
        'executor']
    assert final_da['id-3'].tags['executor'] < final_da['id-3'].tags['on_done']
Beispiel #6
0
async def _ping(host: str, port: int):
    """
    Ping to check if we can connect to gateway via gRPC `host:port`

    Note: Make sure Flow is running
    """
    kwargs = {'port_expose': port, 'host': host}
    _, args, _ = ArgNamespace.get_parsed_args(kwargs, set_client_cli_parser())
    client = Client(args)
    try:
        # TODO: this introduces side-effect, need to be refactored. (2020.01.10)
        client.index(input_fn=['abc'])
        return {'status_code': status.HTTP_200_OK, 'detail': 'connected'}
    except Exception:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f'Cannot connect to GRPC Server on {host}:{port}')
Beispiel #7
0
def _fetch_client(client: GatewayClients):
    gateway_data_host = f'{os.getenv("JINA_GATEWAY_HOST") if os.getenv("JINA_GATEWAY_HOST") else "localhost"}'
    gateway_data_port = f'{os.getenv("JINA_GATEWAY_PORT_EXPOSE") if os.getenv("JINA_GATEWAY_PORT_EXPOSE") else "23456"}'
    args = set_client_cli_parser().parse_args(
        ['--host', gateway_data_host, '--port-expose',
         str(gateway_data_port)])
    return Client(args) if client == GatewayClients.GRPC else WebSocketClient(
        args)
def send_requests(
    client_kwargs,
    stop_event: multiprocessing.Event,
    scale_event: multiprocessing.Event,
    received_responses: multiprocessing.Queue,
    response_arrival_times: multiprocessing.Queue,
    logger,
):
    from jina.clients import Client

    client = Client(**client_kwargs)
    client.show_progress = True

    class ResponseValidator:
        def __init__(
            self,
            received_resposes: multiprocessing.Queue,
            response_arrival_times: multiprocessing.Queue,
        ):
            self.prev_time = None
            self.received_resposes = received_resposes
            self.response_arrival_times = response_arrival_times

        def process_response(self, req):
            logger.debug(f'Received response {req.data.docs[0].text}')
            self.received_resposes.put(req.data.docs[0].text)
            if self.prev_time is not None:
                self.response_arrival_times.put(time.time() - self.prev_time)
            self.prev_time = time.time()

    validator = ResponseValidator(received_responses, response_arrival_times)

    async def async_inputs():
        for i in range(50):
            yield Document(text=f'{i}')
            if stop_event.is_set():
                logger.debug(f'stop sending new requests after {i} requests')
            else:
                await asyncio.sleep(1.0 if scale_event.is_set() else 0.05)

    client.post(
        '/',
        inputs=async_inputs,
        request_size=1,
        on_done=validator.process_response,
    )
Beispiel #9
0
def test_all_sync_clients(protocol, mocker):
    f = Flow(protocol=protocol).add(uses=MyExec)
    docs = list(random_docs(1000))
    m1 = mocker.Mock()
    m2 = mocker.Mock()
    m3 = mocker.Mock()
    m4 = mocker.Mock()
    with f:
        c = Client(host='localhost', port=f.port_expose, protocol=protocol)
        c.post('/', on_done=m1)
        c.post('/foo', docs, on_done=m2)
        c.post('/foo', on_done=m3)
        c.post('/foo', docs, parameters={'hello': 'world'}, on_done=m4)

    m1.assert_called_once()
    m2.assert_called()
    m3.assert_called_once()
    m4.assert_called()
Beispiel #10
0
def client(args: 'Namespace'):
    """
    Start a client connects to the gateway

    :param args: arguments coming from the CLI.
    """
    from jina.clients import Client

    Client(args)
Beispiel #11
0
def test_independent_client():
    with Flow() as f:
        c = Client(port_expose=f.port_expose)
        c.post('/')

    with Flow(restful=True) as f:
        c = WebSocketClient(port_expose=f.port_expose)
        c.post('/')
Beispiel #12
0
def test_client_websocket(mocker, flow_with_websocket):
    with flow_with_websocket:
        time.sleep(0.5)
        client = Client(
            host='localhost',
            port=str(flow_with_websocket.port_expose),
            protocol='websocket',
        )
        # Test that a regular index request triggers the correct callbacks
        on_always_mock = mocker.Mock()
        on_error_mock = mocker.Mock()
        on_done_mock = mocker.Mock()
        client.post(
            '',
            random_docs(1),
            request_size=1,
            on_always=on_always_mock,
            on_error=on_error_mock,
            on_done=on_done_mock,
        )
        on_always_mock.assert_called_once()
        on_done_mock.assert_called_once()
        on_error_mock.assert_not_called()
Beispiel #13
0
def test_incremental_indexing_sequential_indexers(random_workspace):
    total_docs = 20
    duplicate_docs, num_uniq_docs = get_duplicate_docs(num_docs=total_docs)

    f = (Flow().add(uses=os.path.join(cur_dir, 'uniq_vectorindexer.yml')).add(
        uses=os.path.join(cur_dir, 'uniq_docindexer.yml')))

    Client.check_input(duplicate_docs[:10])
    Client.check_input(duplicate_docs)

    with f:
        f.index(duplicate_docs[:10])

    with f:
        f.index(duplicate_docs)

    with BaseExecutor.load(random_workspace / 'vec_idx.bin') as vector_indexer:
        assert isinstance(vector_indexer, NumpyIndexer)
        assert vector_indexer._size == num_uniq_docs

    with BaseExecutor.load(random_workspace / 'doc_idx.bin') as doc_indexer:
        assert isinstance(doc_indexer, BinaryPbIndexer)
        assert doc_indexer._size == num_uniq_docs
Beispiel #14
0
async def run_test(flow, endpoint, num_docs=10, request_size=10):
    # start port forwarding
    from jina.clients import Client

    client_kwargs = dict(
        host='localhost',
        port=flow.port_expose,
        asyncio=True,
    )
    client_kwargs.update(flow._common_kwargs)

    client = Client(**client_kwargs)
    client.show_progress = True
    responses = []
    async for resp in client.post(
        endpoint,
        inputs=[Document() for _ in range(num_docs)],
        return_results=True,
        request_size=request_size,
    ):
        responses.append(resp)

    return responses
Beispiel #15
0
async def run_test(flow,
                   core_client,
                   namespace,
                   endpoint,
                   n_docs=10,
                   request_size=100):
    # start port forwarding
    from jina.clients import Client

    gateway_pod_name = (core_client.list_namespaced_pod(
        namespace=namespace,
        label_selector='app=gateway').items[0].metadata.name)
    config_path = os.environ['KUBECONFIG']
    import portforward

    with portforward.forward(namespace, gateway_pod_name, flow.port, flow.port,
                             config_path):
        client_kwargs = dict(
            host='localhost',
            port=flow.port,
            return_responses=True,
            asyncio=True,
        )
        client_kwargs.update(flow._common_kwargs)

        client = Client(**client_kwargs)
        client.show_progress = True
        responses = []
        async for resp in client.post(
                endpoint,
                inputs=[Document() for _ in range(n_docs)],
                request_size=request_size,
        ):
            responses.append(resp)

    return responses
Beispiel #16
0
 def client(gen, port, protocol):
     Client(protocol=protocol, port=port).post(on='/index',
                                               inputs=gen,
                                               request_size=1)
Beispiel #17
0
def test_multiple_clients(prefetch, protocol, monkeypatch,
                          simple_graph_dict_indexer):
    GOOD_CLIENTS = 5
    GOOD_CLIENT_NUM_DOCS = 20
    MALICIOUS_CLIENT_NUM_DOCS = 50

    def get_document(i):
        return Document(
            id=f'{multiprocessing.current_process().name}_{i}',
            text=str(bytes(bytearray(os.urandom(512 * 4)))),
        )

    async def good_client_gen():
        for i in range(GOOD_CLIENT_NUM_DOCS):
            yield get_document(i)
            await asyncio.sleep(0.1)

    async def malicious_client_gen():
        for i in range(1000, 1000 + MALICIOUS_CLIENT_NUM_DOCS):
            yield get_document(i)

    def client(gen, port, protocol):
        Client(protocol=protocol, port=port).post(on='/index',
                                                  inputs=gen,
                                                  request_size=1)

    monkeypatch.setattr(
        networking.GrpcConnectionPool,
        'send_requests_once',
        DummyMockConnectionPool.send_requests_once,
    )
    port_in = random_port()

    pool = []
    runtime_process = multiprocessing.Process(
        target=create_runtime,
        kwargs={
            'protocol': protocol,
            'port_in': port_in,
            'graph_dict': simple_graph_dict_indexer,
            'prefetch': prefetch,
        },
    )
    runtime_process.start()
    time.sleep(1.0)
    # We have 5 good clients connecting to the same gateway. They have controlled requests.
    # Each client sends `GOOD_CLIENT_NUM_DOCS` (20) requests and sleeps after each request.
    for i in range(GOOD_CLIENTS):
        cp = multiprocessing.Process(
            target=partial(client, good_client_gen, port_in, protocol),
            name=f'goodguy_{i}',
        )
        cp.start()
        pool.append(cp)

    # and 1 malicious client, sending lot of requests (trying to block others)
    cp = multiprocessing.Process(
        target=partial(client, malicious_client_gen, port_in, protocol),
        name='badguy',
    )
    cp.start()
    pool.append(cp)

    for p in pool:
        p.join()

    order_of_ids = list(
        Client(protocol=protocol,
               port=port_in).post(on='/status',
                                  inputs=[Document()],
                                  return_results=True)[0].docs[0].tags['ids'])
    # There must be total 150 docs indexed.

    runtime_process.terminate()
    runtime_process.join()
    assert (len(order_of_ids) == GOOD_CLIENTS * GOOD_CLIENT_NUM_DOCS +
            MALICIOUS_CLIENT_NUM_DOCS)
    """
    If prefetch is set, each Client is allowed (max) 5 requests at a time.
    Since requests are controlled, `badguy` has to do the last 20 requests.

    If prefetch is disabled, clients can freeflow requests. No client is blocked.
    Hence last 20 requests go from `goodguy`.
    (Ideally last 30 requests should be validated, to avoid flaky CI, we test last 20)

    When there are no rules, badguy wins! With rule, you find balance in the world.
    """
    if protocol == 'http':
        # There's no prefetch for http.
        assert set(map(lambda x: x.split('_')[0],
                       order_of_ids[-20:])) == {'goodguy'}
    elif prefetch == 5:
        assert set(map(lambda x: x.split('_')[0],
                       order_of_ids[-20:])) == {'badguy'}
    elif prefetch == 0:
        assert set(map(lambda x: x.split('_')[0],
                       order_of_ids[-20:])) == {'goodguy'}
Beispiel #18
0
Datei: api.py Projekt: yuanl/jina
def client(args: 'Namespace'):
    """Start a client connects to the gateway"""
    from jina.clients import Client
    Client(args)
Beispiel #19
0
def test_querylang_request():
    qs = QueryLang(SliceQL(start=1, end=4, priority=1))
    Client.check_input(random_docs(10), queryset=qs)
Beispiel #20
0
def test_querylang_request():
    qs = QueryLang({'name': 'SliceQL', 'parameters': {'start': 1, 'end': 4}, 'priority': 1})
    Client.check_input(random_docs(10), queryset=qs)
Beispiel #21
0
def client():
    return Client(host='localhost', port=45678)
Beispiel #22
0
def test_check_input_fail(inputs):
    client = Client(host='localhost', port_jinad=12345)
    with pytest.raises(BadClientInput):
        client.check_input(inputs)
Beispiel #23
0
def test_check_input_success(inputs):
    client = Client(host='localhost', port_jinad=12345)
    client.check_input(inputs)
Beispiel #24
0
def test_check_input_fail(inputs):
    with pytest.raises(BadClientInput):
        Client.check_input(inputs)
def get_client(port):
    args = set_client_cli_parser().parse_args(
        ['--host', 'localhost', '--port',
         str(port)])

    return Client(args)
Beispiel #26
0
 def client(gen, port, protocol):
     Client(protocol=protocol, port=port, return_responses=True).post(
         on='/index', inputs=gen, request_size=1
     )
Beispiel #27
0
def test_check_input_success(inputs):
    Client.check_input(inputs)
Beispiel #28
0
def test_client_from_kwargs(protocol):
    Client(port=12345, host='0.0.0.1', protocol=protocol)
Beispiel #29
0
def client():
    args = set_client_cli_parser().parse_args(
        ['--host', 'localhost', '--port-expose', '45678'])

    return Client(args)
Beispiel #30
0
def test_independent_client(protocol):
    with Flow(protocol=protocol) as f:
        c = Client(host='localhost', port=f.port_expose, protocol=protocol)
        assert type(c) == type(f.client)
        c.post('/')