Пример #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
Пример #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,
    )
Пример #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
Пример #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,
    )
Пример #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']
Пример #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}')
Пример #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,
    )
Пример #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()
Пример #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)
Пример #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('/')
Пример #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()
Пример #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
Пример #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
Пример #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
Пример #16
0
 def client(gen, port, protocol):
     Client(protocol=protocol, port=port).post(on='/index',
                                               inputs=gen,
                                               request_size=1)
Пример #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'}
Пример #18
0
Файл: api.py Проект: yuanl/jina
def client(args: 'Namespace'):
    """Start a client connects to the gateway"""
    from jina.clients import Client
    Client(args)
Пример #19
0
def test_querylang_request():
    qs = QueryLang(SliceQL(start=1, end=4, priority=1))
    Client.check_input(random_docs(10), queryset=qs)
Пример #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)
Пример #21
0
def client():
    return Client(host='localhost', port=45678)
Пример #22
0
def test_check_input_fail(inputs):
    client = Client(host='localhost', port_jinad=12345)
    with pytest.raises(BadClientInput):
        client.check_input(inputs)
Пример #23
0
def test_check_input_success(inputs):
    client = Client(host='localhost', port_jinad=12345)
    client.check_input(inputs)
Пример #24
0
def test_check_input_fail(inputs):
    with pytest.raises(BadClientInput):
        Client.check_input(inputs)
Пример #25
0
def get_client(port):
    args = set_client_cli_parser().parse_args(
        ['--host', 'localhost', '--port',
         str(port)])

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

    return Client(args)
Пример #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('/')