{"id":24694462,"url":"https://github.com/roadrunner-php/centrifugo","last_synced_at":"2025-10-09T01:31:06.599Z","repository":{"id":62162791,"uuid":"557776564","full_name":"roadrunner-php/centrifugo","owner":"roadrunner-php","description":"🔌 RoadRunner Centrifugo Bridge","archived":false,"fork":false,"pushed_at":"2025-06-23T08:26:31.000Z","size":1598,"stargazers_count":12,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"2.x","last_synced_at":"2025-08-26T08:19:13.912Z","etag":null,"topics":["centrifugo","grpc","php","pubsub","roadrunner","websocket"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":false,"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/roadrunner-php.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"roadrunner-server"}},"created_at":"2022-10-26T09:29:31.000Z","updated_at":"2025-06-23T08:24:58.000Z","dependencies_parsed_at":"2024-04-11T18:30:32.887Z","dependency_job_id":"fdbfa0fa-8572-465a-b2bd-b8d2ffa9a4c4","html_url":"https://github.com/roadrunner-php/centrifugo","commit_stats":{"total_commits":26,"total_committers":3,"mean_commits":8.666666666666666,"dds":"0.46153846153846156","last_synced_commit":"703b2eabd2b85f676b0b3aa389ee93804f69a250"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/roadrunner-php/centrifugo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Fcentrifugo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Fcentrifugo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Fcentrifugo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Fcentrifugo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roadrunner-php","download_url":"https://codeload.github.com/roadrunner-php/centrifugo/tar.gz/refs/heads/2.x","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Fcentrifugo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000725,"owners_count":26082895,"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","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["centrifugo","grpc","php","pubsub","roadrunner","websocket"],"created_at":"2025-01-26T23:59:47.740Z","updated_at":"2025-10-09T01:31:06.235Z","avatar_url":"https://github.com/roadrunner-php.png","language":"PHP","funding_links":["https://github.com/sponsors/roadrunner-server"],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://roadrunner.dev\" target=\"_blank\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/roadrunner-server/.github/assets/8040338/e6bde856-4ec6-4a52-bd5b-bfe78736c1ff\"\u003e\n    \u003cimg align=\"center\" src=\"https://github.com/roadrunner-server/.github/assets/8040338/040fb694-1dd3-4865-9d29-8e0748c2c8b8\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\n# RoadRunner Centrifugo Bridge\n\n[![PHP Version Require](https://poser.pugx.org/roadrunner-php/centrifugo/require/php)](https://packagist.org/packages/roadrunner-php/centrifugo)\n[![Latest Stable Version](https://poser.pugx.org/roadrunner-php/centrifugo/v/stable)](https://packagist.org/packages/roadrunner-php/centrifugo)\n[![phpunit](https://github.com/roadrunner-php/centrifugo/actions/workflows/phpunit.yml/badge.svg)](https://github.com/roadrunner-php/centrifugo/actions)\n[![psalm](https://github.com/roadrunner-php/centrifugo/actions/workflows/psalm.yml/badge.svg)](https://github.com/roadrunner-php/centrifugo/actions)\n[![Codecov](https://codecov.io/gh/roadrunner-php/centrifugo/branch/master/graph/badge.svg)](https://codecov.io/gh/roadrunner-php/centrifugo/)\n[![Total Downloads](https://poser.pugx.org/roadrunner-php/centrifugo/downloads)](https://packagist.org/packages/roadrunner-php/centrifugo)\n\nThis repository contains the codebase PHP bridge using RoadRunner centrifuge plugin.\n\n## Installation\n\nTo install application server and Jobs codebase\n\n```bash\ncomposer require roadrunner-php/centrifugo\n```\n\nYou can use the convenient installer to download the latest available compatible version of RoadRunner assembly:\n\n```bash\ncomposer require spiral/roadrunner-cli --dev\nvendor/bin/rr get\n```\n\n## Proxy Centrifugo requests to a PHP application\n\nIt's possible to proxy some client connection events from Centrifugo to the RoadRunner application server and react to\nthem in a custom way. For example, it's possible to authenticate connection via request from Centrifugo to application\nbackend, refresh client sessions and answer to RPC calls sent by a client over bidirectional connection.\n\nThe list of events that can be proxied:\n\n* `connect` – called when a client connects to Centrifugo, so it's possible to authenticate user, return custom data to a\nclient, subscribe connection to several channels, attach meta information to the connection, and so on. Works for\nbidirectional and unidirectional transports.\n* `refresh` - called when a client session is going to expire, so it's possible to prolong it or just let it expire. Can\nalso be used just as a periodical connection liveness callback from Centrifugo to app backend. Works for bidirectional\nand unidirectional transports.\n* `sub_refresh` - called when it's time to refresh the subscription. Centrifugo itself will ask your backend about subscription validity instead of subscription refresh workflow on the client-side.\n* `subscribe` - called when clients try to subscribe on a channel, so it's possible to check permissions and return custom\ninitial subscription data. Works for bidirectional transports only.\n* `publish` - called when a client tries to publish into a channel, so it's possible to check permissions and optionally\nmodify publication data. Works for bidirectional transports only.\n* `rpc` - called when a client sends RPC, you can do whatever logic you need based on a client-provided RPC method and\nparams. Works for bidirectional transports only.\n\nFirst you need to add `centrifuge` section to your RoadRunner configuration. For example, such a configuration\nwould be quite feasible to run:\n\n```yaml\nrpc:\n  listen: tcp://127.0.0.1:6001\n\nserver:\n  command: \"php app.php\"\n  relay: pipes\n\ncentrifuge:\n  proxy_address: \"tcp://0.0.0.0:10001\" # Centrifugo address\n```\n\nand centrifugo config:\n\n```json\n{\n  \"admin\": true,\n  \"api_key\": \"secret\",\n  \"admin_password\": \"password\",\n  \"admin_secret\": \"admin_secret\",\n  \"allowed_origins\": [\n    \"*\"\n  ],\n  \"token_hmac_secret_key\": \"test\",\n  \"publish\": true,\n  \"proxy_publish\": true,\n  \"proxy_subscribe\": true,\n  \"proxy_connect\": true,\n  \"allow_subscribe_for_client\": true,\n  \"proxy_connect_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_connect_timeout\": \"10s\",\n  \"proxy_publish_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_publish_timeout\": \"10s\",\n  \"proxy_subscribe_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_subscribe_timeout\": \"10s\",\n  \"proxy_refresh_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_refresh_timeout\": \"10s\",\n  \"proxy_sub_refresh_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_sub_refresh_timeout\": \"1s\",\n  \"proxy_rpc_endpoint\": \"grpc://127.0.0.1:10001\",\n  \"proxy_rpc_timeout\": \"10s\"\n}\n```\n\n\u003e **Note**\n\u003e `proxy_connect_endpoint`, `proxy_publish_endpoint`, `proxy_subscribe_endpoint`, `proxy_refresh_endpoint`,\n\u003e `proxy_sub_refresh_endpoint`, `proxy_rpc_endpoint` - endpoint address of roadrunner server with activated\n\u003e `centrifuge` plugin.\n\nTo init abstract RoadRunner worker:\n\n```php\n\u003c?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\nuse RoadRunner\\Centrifugo\\CentrifugoWorker;\nuse RoadRunner\\Centrifugo\\Payload;\nuse RoadRunner\\Centrifugo\\Request;\nuse RoadRunner\\Centrifugo\\Request\\RequestFactory;\nuse Spiral\\RoadRunner\\Worker;\n\n$worker = Worker::create();\n$requestFactory = new RequestFactory($worker);\n\n// Create a new Centrifugo Worker from global environment\n$centrifugoWorker = new CentrifugoWorker($worker, $requestFactory);\n\nwhile ($request = $centrifugoWorker-\u003ewaitRequest()) {\n\n    if ($request instanceof Request\\Invalid) {\n        $errorMessage = $request-\u003egetException()-\u003egetMessage();\n\n        if ($request-\u003egetException() instanceof \\RoadRunner\\Centrifugo\\Exception\\InvalidRequestTypeException) {\n            $payload = $request-\u003egetException()-\u003epayload;\n        }\n\n        // Handle invalid request\n        // $logger-\u003eerror($errorMessage, $payload ?? []);\n\n        continue;\n    }\n\n    if ($request instanceof Request\\Refresh) {\n        try {\n            // Do something\n            $request-\u003erespond(new Payload\\RefreshResponse(\n                // ...\n            ));\n        } catch (\\Throwable $e) {\n            $request-\u003eerror($e-\u003egetCode(), $e-\u003egetMessage());\n        }\n\n        continue;\n    }\n\n    if ($request instanceof Request\\Subscribe) {\n        try {\n            // Do something\n            $request-\u003erespond(new Payload\\SubscribeResponse(\n                // ...\n            ));\n\n            // You can also disconnect connection\n            $request-\u003edisconnect('500', 'Connection is not allowed.');\n        } catch (\\Throwable $e) {\n            $request-\u003eerror($e-\u003egetCode(), $e-\u003egetMessage());\n        }\n\n        continue;\n    }\n\n    if ($request instanceof Request\\Publish) {\n        try {\n            // Do something\n            $request-\u003erespond(new Payload\\PublishResponse(\n                // ...\n            ));\n\n            // You can also disconnect connection\n            $request-\u003edisconnect('500', 'Connection is not allowed.');\n        } catch (\\Throwable $e) {\n            $request-\u003eerror($e-\u003egetCode(), $e-\u003egetMessage());\n        }\n\n        continue;\n    }\n\n    if ($request instanceof Request\\RPC) {\n        try {\n            $response = $router-\u003ehandle(\n                new Request(uri: $request-\u003emethod, data: $request-\u003edata),\n            ); // ['user' =\u003e ['id' =\u003e 1, 'username' =\u003e 'john_smith']]\n\n            $request-\u003erespond(new Payload\\RPCResponse(\n                data: $response\n            ));\n        } catch (\\Throwable $e) {\n            $request-\u003eerror($e-\u003egetCode(), $e-\u003egetMessage());\n        }\n\n        continue;\n    }\n}\n```\n\n\u003e **Note**\n\u003e You can find addition information about [here](https://centrifugal.dev/docs/server/proxy).\n\n\u003ca href=\"https://spiral.dev/\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/773481/220979012-e67b74b5-3db1-41b7-bdb0-8a042587dedc.jpg\" alt=\"try Spiral Framework\" /\u003e\n\u003c/a\u003e\n\n## License\n\nThe MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information. Maintained\nby [Spiral Scout](https://spiralscout.com).\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froadrunner-php%2Fcentrifugo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froadrunner-php%2Fcentrifugo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froadrunner-php%2Fcentrifugo/lists"}