Using Future Mode

edit

Utilizing this feature is relatively straightforward, but it does introduce more responsibility into your code. To enable future mode, set the future flag in the client options to 'lazy':

$client = ClientBuilder::create()->build();

$params = [
    'index' => 'test',
    'type' => 'test',
    'id' => 1,
    'client' => [
        'future' => 'lazy'
    ]
];

$future = $client->get($params);

This will return a future, rather than the actual response. A future represents a future computation and acts like a placeholder. You can pass a future around your code like a regular object. When you need the result values, you can resolve the future. If the future has already resolved (due to some other activity), the values will be immediately available. If the future has not resolved yet, the resolution will block until those values have become available (e.g. after the API call completes).

In practice, this means you can queue up a batch of requests by using future: lazy and they will pend until you resolve the futures, at which time all requests will be sent in parallel to the cluster and return asynchronously to curl.

This sounds tricky, but it is actually very simple thanks to RingPHP’s FutureArray interface, which makes the future act like a simple associative array. For example:

$client = ClientBuilder::create()->build();

$params = [
    'index' => 'test',
    'type' => 'test',
    'id' => 1,
    'client' => [
        'future' => 'lazy'
    ]
];

$future = $client->get($params);

$doc = $future['_source'];    // This call will block and force the future to resolve

Interacting with the future as an associative array, just like a normal response, will cause the future to resolve that particular value (which in turn resolves all pending requests and values). This allows patterns such as:

$client = ClientBuilder::create()->build();
$futures = [];

for ($i = 0; $i < 1000; $i++) {
    $params = [
        'index' => 'test',
        'type' => 'test',
        'id' => $i,
        'client' => [
            'future' => 'lazy'
        ]
    ];

    $futures[] = $client->get($params);     //queue up the request
}


foreach ($futures as $future) {
    // access future's values, causing resolution if necessary
    echo $future['_source'];
}

The queued requests will execute in parallel and populate their futures after execution. Batch size defaults to 100 requests-per-batch.

If you wish to force future resolution, but don’t actually need the values immediately, you can call wait() on the future to force resolution too:

$client = ClientBuilder::create()->build();
$futures = [];

for ($i = 0; $i < 1000; $i++) {
    $params = [
        'index' => 'test',
        'type' => 'test',
        'id' => $i,
        'client' => [
            'future' => 'lazy'
        ]
    ];

    $futures[] = $client->get($params);     //queue up the request
}

//wait() forces future resolution and will execute the underlying curl batch
$futures[999]->wait();