{"id":14983571,"url":"https://github.com/spiral/grpc-client","last_synced_at":"2025-10-24T05:31:54.175Z","repository":{"id":250316469,"uuid":"833588731","full_name":"spiral/grpc-client","owner":"spiral","description":"PHP client for gRPC","archived":false,"fork":false,"pushed_at":"2024-12-11T09:41:06.000Z","size":465,"stargazers_count":8,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-31T00:13:02.543Z","etag":null,"topics":["grpc","grpc-client","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spiral.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"spiral"}},"created_at":"2024-07-25T10:56:20.000Z","updated_at":"2024-12-11T09:41:09.000Z","dependencies_parsed_at":"2024-09-24T15:24:36.698Z","dependency_job_id":"c5178185-5102-4314-9fca-c636becaa573","html_url":"https://github.com/spiral/grpc-client","commit_stats":{"total_commits":26,"total_committers":1,"mean_commits":26.0,"dds":0.0,"last_synced_commit":"cd5871b5adb19fe2a448d1e6df13d555b92fcd9c"},"previous_names":["spiral/grpc-client"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiral%2Fgrpc-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiral%2Fgrpc-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiral%2Fgrpc-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spiral%2Fgrpc-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spiral","download_url":"https://codeload.github.com/spiral/grpc-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237918710,"owners_count":19387305,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grpc","grpc-client","php"],"created_at":"2024-09-24T14:07:27.214Z","updated_at":"2025-10-24T05:31:49.130Z","avatar_url":"https://github.com/spiral.png","language":"PHP","funding_links":["https://github.com/sponsors/spiral"],"categories":[],"sub_categories":[],"readme":"# gRPC Client\n\nThe package provides powerful and convenient functionality for making client gRPC requests through\na simple and extensible interface.\n\n## Installation\n\n```bash\ncomposer require spiral/grpc-client -W\n```\n\n[![PHP](https://img.shields.io/packagist/php-v/spiral/grpc-client.svg?style=flat-square\u0026logo=php)](https://packagist.org/packages/spiral/grpc-client)\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/spiral/grpc-client.svg?style=flat-square\u0026logo=packagist)](https://packagist.org/packages/spiral/grpc-client)\n[![License](https://img.shields.io/packagist/l/spiral/grpc-client.svg?style=flat-square)](LICENSE.md)\n[![Total downloads](https://img.shields.io/packagist/dt/spiral/grpc-client.svg?style=flat-square)](https://packagist.org/packages/spiral/grpc-client/stats)\n\nNote that the package requires [gRPC extension](https://pecl.php.net/package/gRPC) to be installed.\n\n## Documentation\n\n### Public API\n\nThe package provides the following parts of the API:\n- Integration classes for use with frameworks.\n- Classes for convenient package configuration through DTOs.\n- A set of basic [interceptors](https://spiral.dev/docs/framework-interceptors/).\n- Several types of exceptions for error handling.\n\n### Integration\n\n#### Spiral\n\n\u003e [!NOTE]\n\u003e The [`spiral/roadrunner-bridge`](https://github.com/spiral/roadrunner-bridge) package includes\n\u003e the `spiral/grpc-client` package by default since version `4.0.0` and provides its integration\n\u003e and configuration flow.\n\nAdd the `\\Spiral\\Grpc\\Client\\Bridge\\GrpcClientBootloader` bootloader to the list of bootloaders\nin the application configuration (usually it is `Kernel.php`).\n\n#### Other Frameworks\n\nIf you are using this package outside the [Spiral](https://spiral.dev/) framework,\nyou need to figure out how to use the `\\Spiral\\Grpc\\Client\\ServiceClientProvider` provider\nto get ready-to-use gRPC clients.\n\n### Configuration DTOs\n\nNow let's consider a configuration example:\n\n```php\nuse Spiral\\Grpc\\Client\\Config\\GrpcClientConfig;\nuse Spiral\\Grpc\\Client\\Config\\ServiceConfig;\nuse Spiral\\Grpc\\Client\\Config\\ConnectionConfig;\nuse Spiral\\Grpc\\Client\\Interceptor\\SetTimoutInterceptor;\nuse Spiral\\Grpc\\Client\\Interceptor\\RetryInterceptor;\nuse Spiral\\Grpc\\Client\\Interceptor\\ExecuteServiceInterceptors;\n\nnew GrpcClientConfig(\n    interceptors: [\n        SetTimoutInterceptor::createConfig(10_000), // 10 seconds\n        RetryInterceptor::createConfig(\n            maximumAttempts: 3,\n            initialInterval: 100, // 0.1 seconds\n            backoffCoefficient: 1.5,\n        ),\n        ExecuteServiceInterceptors::class,\n    ],\n    services: [\n        new ServiceConfig(\n            connections: new ConnectionConfig('my-service:9001'),\n            interfaces: [\n                \\GRPC\\MyService\\MailSenderInterface::class,\n                \\GRPC\\MyService\\BlackListInterface::class,\n                \\GRPC\\MyService\\SubscriberInterface::class,\n            ],\n        ),\n    ],\n)\n```\n\n#### GrpcClientConfig\n\nThis class represents the configuration of the gRPC client in general.\nIt includes a list of service configurations and a general list of interceptors that will be applied to all services.\n\nInterceptors can be declared as class names, `Spiral\\Core\\Container\\Autowire` objects\n(if custom constructor arguments need to be passed), or objects.\nNote that some interceptors provide convenient methods for creating configurations.\n\n#### ServiceConfig\n\nThis class represents the configuration of a specific service or a group of similar services\nbut with different connection options.\n\nThe `interfaces` parameter is a list of gRPC service interfaces that were generated by the `protoc` utility\nand that are implemented by the service.\n\n\u003e [!NOTE]\n\u003e Currently, we support only service interfaces that are [generated](https://spiral.dev/docs/grpc-client)\n\u003e using the `protoc` utility with the `protoc-gen-php-grpc` plugin.\n\nThe configuration example above doesn't include the `interceptors` parameter.\nIt's the same as in the general configuration, but it's applied only to the specified service.\nThis branch of interceptors is run via the `ExecuteServiceInterceptors` interceptor.\nSo, it's important to include it if you want to use service-specific interceptors.\n\nThe `connections` parameter is a list of connection configurations. You can specify multiple connections\nto distribute the load between them or to provide fail-over.\nMulti-connection orchestration strategy can be configured by interceptors,\nfor example, `ConnectionsRotationInterceptor`.\n\n#### ConnectionConfig\n\nThis class represents the configuration of a single connection to the gRPC service.\nIt includes credentials and the service address.\n\nTo create a secure connection, use the `TlsConfig` class.\n\n```php\nnew ConnectionConfig(\n    address: 'my-service:9001',\n    tls: new TlsConfig(\n        privateKey: '/my-project.key',\n        certChain: '/my-project.pem',\n    ),\n),\n```\n\n### Usage\n\nAfter the integration and configuration are ready, you can get the client for the desired service interface\nfrom the container and call the service methods.\n\n```php\nfinal class Sender\n{\n    public function __construct(\n        private \\GRPC\\MyService\\MailSenderInterface $mailSender,\n    ) {}\n\n    public function sendMail(string $email, $subject, string $message): bool\n    {\n        $request = (new \\GRPC\\MyService\\SendMailRequest())\n            -\u003esetEmail($email)\n            -\u003esetSubject($subject)\n            -\u003esetMessage($message);\n\n        $response = $this-\u003emailSender-\u003esendMail(new \\Spiral\\RoadRunner\\GRPC\\Context([]), $request);\n        return $response-\u003egetSuccess();\n    }\n}\n```\n\n### Interceptors\n\nImportant points when using interceptors in the [long-running](https://spiral.dev/docs/start-server) mode:\n- **Stateful**: interceptors are recreated anew for each request, so you can safely store the state of each call.\n- **Scoped**: interceptors are created in the same Container Scope in which the client is called.\n  Accordingly, you can request contextual dependencies in the interceptor's constructor.\n\nWhen writing your own interceptors, you will likely want to work with gRPC-specific fields\n(options, metadata, input message, etc.).\nUse the `\\Spiral\\Grpc\\Client\\Interceptor\\Helper` class to get or set the values of these context fields.\n\n```php\nfinal class AuthContextInterceptor implements InterceptorInterface\n{\n    public function __construct(\n        private readonly AuthContextInterface $authContext,\n    ) {}\n\n    public function intercept(CallContextInterface $context, HandlerInterface $handler): mixed\n    {\n        $token = $this-\u003eauthContext-\u003egetToken();\n\n        if ($token === null) {\n            return $handler-\u003ehandle($context);\n        }\n\n        $metadata = \\Spiral\\Grpc\\Client\\Interceptor\\Helper::withMetadata($context);\n        $metadata['auth-token'] = [$token];\n\n        return $handler-\u003ehandle(\\Spiral\\Grpc\\Client\\Interceptor\\Helper::withMetadata($context, $metadata));\n    }\n}\n```\n\n#### Order of Interceptors\n\nInterceptors are executed in the order in which they are declared in the configuration.\nThe order of the interceptors is important.\n\nFor example, if we have the following configuration:\n\n1. `SetTimeout(10 seconds)`\n2. `Retry(maxAttempts: 3, interval: 2 seconds)`\n3. `SetTimeout(3 seconds)`\n\nthen we will have a 3-second timeout for each retry attempt.  \nWe also have a 10-second timeout for all attempts in total, after which **no new request** attempts will be made.\nThis happens because the `RetryInterceptor` takes into account previously configured timeouts.\n\nAlso, the placement of the `ExecuteServiceInterceptors` interceptor,\nwhich embeds the interceptors of the currently running service,\nwill affect the final sequence of interceptors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspiral%2Fgrpc-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspiral%2Fgrpc-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspiral%2Fgrpc-client/lists"}