google/longrunning
Idiomatic PHP client for Google Long‑Running Operations API. Install via Composer and use with REST or gRPC to manage operations (poll, cancel, delete, list) across Google Cloud services. Part of google-cloud-php; authentication/debug guides included.
Install the package:
composer require google/longrunning
For gRPC support (recommended for high-throughput scenarios):
composer require google/longrunning google/grpc
Authenticate (follow Google Cloud PHP Auth Guide):
use Google\Auth\Credentials\ServiceAccountCredentials;
use Google\Cloud\LongRunning\LongRunningClient;
$credentials = ServiceAccountCredentials::fromStream(__DIR__.'/path/to/service-account.json');
$client = new LongRunningClient(['credentials' => $credentials]);
First use case: Poll an operation
$operationName = 'projects/my-project/locations/global/operations/op-123';
$operation = $client->getOperation($operationName);
// Poll until completion (with exponential backoff)
$result = $client->pollUntilDone($operation);
done, error, response).ShouldQueue jobs to offload polling to queues (see Implementation Patterns).Use ShouldQueue to decouple polling from the request lifecycle:
use Google\Cloud\LongRunning\LongRunningClient;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class PollGcpOperation implements ShouldQueue
{
use Dispatchable, Queueable;
public function __construct(
protected string $operationName,
protected LongRunningClient $client
) {}
public function handle()
{
$operation = $this->client->getOperation($this->operationName);
$result = $this->client->pollUntilDone($operation);
// Store result or trigger next job
$this->dispatch(new ProcessOperationResult($result));
}
}
Customize retry logic for cost efficiency:
$operation = $client->getOperation($operationName);
$retryPolicy = new \Google\ApiCore\RetryPolicy([
'maxAttempts' => 10,
'initialBackoff' => 1.0, // seconds
'maxBackoff' => 60.0, // seconds
'backoffFactor' => 2.0,
]);
$result = $client->pollUntilDone($operation, $retryPolicy);
Handle batch operations where some resources succeed/fail:
$filter = 'done=true'; // Only completed operations
$operations = $client->listOperations(
'projects/my-project/locations/global',
['filter' => $filter]
);
foreach ($operations->getOperations() as $op) {
if ($op->getDone()) {
if ($op->getError()) {
// Handle partial failure
logger()->error('Partial failure:', ['operation' => $op->getName()]);
} else {
// Process successful result
$result = $op->getResponse();
}
}
}
Abort long-running tasks (e.g., user-triggered cancellation):
$operationName = 'projects/my-project/locations/global/operations/op-123';
$client->cancelOperation($operationName);
ListOperations with server-side pagination).ext-grpc dependency).Configure transport in the client:
$client = new LongRunningClient([
'credentials' => $credentials,
'transport' => 'grpc', // or 'rest'
]);
Service Provider Binding:
Bind the client in AppServiceProvider for dependency injection:
public function register()
{
$this->app->singleton(LongRunningClient::class, function ($app) {
$credentials = ServiceAccountCredentials::fromStream(
$app['path.to.service.account']
);
return new LongRunningClient(['credentials' => $credentials]);
});
}
Horizon Dashboard Integration: Extend Horizon’s job table to display GCP operation statuses:
// In a Horizon dashboard widget
$operationName = $job->payload['operation_name'];
$operation = $client->getOperation($operationName);
return view('horizon.job', [
'status' => $operation->getDone() ? 'Completed' : 'Running',
'progress' => $operation->getMetadata()['progress'] ?? 0,
]);
Event-Driven Polling: Use Laravel Events to trigger actions on operation completion:
// After polling completes
event(new GcpOperationCompleted($operationName, $result));
Listen in an Event Service Provider:
protected $listen = [
GcpOperationCompleted::class => [
SendSlackNotification::class,
UpdateDatabase::class,
],
];
$client = new LongRunningClient([
'credentials' => $credentials,
'logger' => new \Monolog\Logger('gcp_operations'),
]);
$start = microtime(true);
$result = $client->pollUntilDone($operation);
$duration = microtime(true) - $start;
\App\Models\OperationMetric::create([
'operation_name' => $operationName,
'duration_seconds' => $duration,
]);
Credential Handling:
config/services.php:
'google' => [
'service_account' => env('GOOGLE_SERVICE_ACCOUNT_JSON'),
],
Operation Name Format:
projects/{project}/locations/{location}/operations/{operation_id}
projects/my-project/locations/us/operations/op-123
NOT_FOUND errors. Double-check with the service’s documentation.gRPC Dependencies:
ext-grpc:
pecl install grpc
Exponential Backoff Misconfiguration:
RetryPolicy:
$retryPolicy = new \Google\ApiCore\RetryPolicy([
'initialBackoff' => 0.5, // Start with 500ms
'maxBackoff' => 30.0, // Cap at 30 seconds
]);
Partial Success Handling:
unreachable resources if some operations fail. Check:
$operations = $client->listOperations($parent, [
'filter' => 'done=true',
'partialSuccess' => true, // Enable partial success flag
]);
partialSuccess is false, unreachable operations are omitted.Timeouts:
$client = new LongRunningClient([
'timeout' => 120, // 120 seconds
]);
How can I help you explore Laravel packages today?