{"id":49822120,"url":"https://github.com/folk-project/folk-plugin-jobs","last_synced_at":"2026-05-14T13:02:14.276Z","repository":{"id":356706869,"uuid":"1232984041","full_name":"Folk-Project/folk-plugin-jobs","owner":"Folk-Project","description":"Queue consumer plugin for Folk — pulls jobs from memory or Redis and dispatches to PHP workers","archived":false,"fork":false,"pushed_at":"2026-05-09T11:19:52.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2026-05-09T11:39:09.499Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Folk-Project.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-08T13:20:01.000Z","updated_at":"2026-05-09T11:19:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Folk-Project/folk-plugin-jobs","commit_stats":null,"previous_names":["folk-project/folk-plugin-jobs"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/Folk-Project/folk-plugin-jobs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Folk-Project%2Ffolk-plugin-jobs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Folk-Project%2Ffolk-plugin-jobs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Folk-Project%2Ffolk-plugin-jobs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Folk-Project%2Ffolk-plugin-jobs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Folk-Project","download_url":"https://codeload.github.com/Folk-Project/folk-plugin-jobs/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Folk-Project%2Ffolk-plugin-jobs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32981600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T11:31:52.688Z","status":"ssl_error","status_checked_at":"2026-05-13T11:31:52.072Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-05-13T12:07:13.119Z","updated_at":"2026-05-14T13:02:13.751Z","avatar_url":"https://github.com/Folk-Project.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# folk-plugin-jobs\n\nQueue consumer plugin for Folk — pulls jobs from memory or Redis and dispatches to PHP workers.\n\n## Configuration\n\nAdd to `folk.build.toml`:\n\n```toml\n[[plugin]]\ncrate_name = \"folk-plugin-jobs\"\nversion = \"0.1\"\nconfig_key = \"jobs\"\n```\n\nConfigure in `folk.toml`:\n\n```toml\n[jobs]\ndriver = \"redis\"                      # \"memory\" or \"redis\"\nredis_url = \"redis://127.0.0.1:6379\"  # only for redis driver\n\n[[jobs.queues]]\nname = \"default\"\nconcurrency = 4\nmax_retries = 3\n\n[[jobs.queues]]\nname = \"emails\"\nconcurrency = 2\nmax_retries = 5\n```\n\n### Settings\n\n#### `[jobs]`\n\n| Key | Type | Default | Description |\n|-----|------|---------|-------------|\n| `driver` | `\"memory\"` \\| `\"redis\"` | `\"memory\"` | Queue backend. `memory` is in-process only (no persistence). |\n| `redis_url` | `String` | `\"redis://127.0.0.1:6379\"` | Redis connection URL (redis driver only). |\n\n#### `[[jobs.queues]]`\n\n| Key | Type | Default | Description |\n|-----|------|---------|-------------|\n| `name` | `String` | `\"default\"` | Queue name. |\n| `concurrency` | `usize` | `4` | Concurrent consumer tasks for this queue. |\n| `max_retries` | `u32` | `3` | Max retries before discarding a failed job. |\n\n### RPC methods\n\n| Method | Description |\n|--------|-------------|\n| `jobs.push` | Push a job to a queue. Params: `{queue: string, payload: string\\|binary}` |\n| `jobs.stats` | Returns queue depth for each configured queue. |\n\n## Usage with folk-sdk (plain PHP)\n\n### Handler\n\n```php\n\u003c?php\n\nuse Folk\\Sdk\\Jobs\\JobsModeHandler;\n\nclass MyJobHandler implements JobsModeHandler\n{\n    public function process(mixed $payload): mixed\n    {\n        // $payload is the raw string that was pushed to the queue.\n        // Parse it however you want — JSON, msgpack, etc.\n        $data = json_decode($payload, true);\n\n        // Do work...\n        file_put_contents('/tmp/job.log', $data['task'] . \"\\n\", FILE_APPEND);\n\n        return ['status' =\u003e 'ok'];\n    }\n}\n```\n\n### Registration\n\n```php\n\u003c?php\n// bin/folk-worker (or your entry point)\n\n$loop = new \\Folk\\Sdk\\Worker\\WorkerLoop();\n$loop-\u003eregisterJobsHandler(new MyJobHandler());\n$loop-\u003erun();\n```\n\n### Pushing jobs\n\nJobs are pushed via the Folk admin RPC socket, not directly to Redis.\nUse the built-in RPC client:\n\n```php\n\u003c?php\n\nuse Folk\\Sdk\\Rpc\\RpcClient;\n\n$rpc = new RpcClient('./tmp/folk.sock');\n\n$rpc-\u003ecall('jobs.push', [\n    'queue'   =\u003e 'default',\n    'payload' =\u003e json_encode(['task' =\u003e 'send-email', 'to' =\u003e 'user@example.com']),\n]);\n```\n\nThis works with both `memory` and `redis` drivers — your code doesn't need to know which driver is used.\n\n## Usage with Laravel (folk-laravel)\n\n### Setup\n\n1. Set queue connection in `.env`:\n\n```env\nQUEUE_CONNECTION=folk\n```\n\n2. Add the `folk` connection to `config/queue.php`:\n\n```php\n'folk' =\u003e [\n    'driver' =\u003e 'folk',\n    'queue' =\u003e 'default',\n],\n```\n\n3. Configure `rpc_socket` in `config/folk.php`:\n\n```php\nreturn [\n    'rpc_socket' =\u003e './tmp/folk.sock',\n];\n```\n\n### Dispatching jobs\n\nUse standard Laravel dispatch — no changes needed:\n\n```php\n// Simple dispatch\nTestJob::dispatch($data);\n\n// To a specific queue\nTestJob::dispatch($data)-\u003eonQueue('emails');\n```\n\nJobs flow through Folk transparently:\n\n```\nLaravel dispatch() --\u003e FolkQueue --\u003e RPC (jobs.push) --\u003e folk-plugin-jobs --\u003e [memory|redis] --\u003e PHP worker --\u003e fire()\n```\n\nLaravel serializes the job, Folk handles routing and storage. Your application code never touches Redis directly.\n\n### Job classes\n\nStandard Laravel job classes work out of the box:\n\n```php\n\u003c?php\n\nnamespace App\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\nuse Illuminate\\Contracts\\Queue\\ShouldQueue;\nuse Illuminate\\Foundation\\Bus\\Dispatchable;\nuse Illuminate\\Queue\\InteractsWithQueue;\n\nclass SendEmail implements ShouldQueue\n{\n    use Dispatchable, InteractsWithQueue, Queueable;\n\n    public function __construct(\n        public readonly string $to,\n        public readonly string $subject,\n    ) {}\n\n    public function handle(): void\n    {\n        // Send the email...\n    }\n}\n```\n\n### Multiple queues\n\nDefine queues in `folk.toml` and dispatch to them by name:\n\n```toml\n[[jobs.queues]]\nname = \"default\"\nconcurrency = 4\n\n[[jobs.queues]]\nname = \"emails\"\nconcurrency = 2\n\n[[jobs.queues]]\nname = \"reports\"\nconcurrency = 1\n```\n\n```php\nSendEmail::dispatch($to, $subject)-\u003eonQueue('emails');\nGenerateReport::dispatch($params)-\u003eonQueue('reports');\n```\n\n## How it works\n\n### Drivers\n\n**Memory** — In-process `VecDeque`. No persistence. Good for development and testing.\n\n**Redis** — `BLPOP` for consumption, `RPUSH` for enqueue. Each queue is a Redis list key. At-least-once semantics.\n\n### Consumer loop\n\nFor each queue, the plugin spawns `concurrency` consumer tasks:\n\n1. `driver.pop(queue)` — blocks until a job is available\n2. Sends payload to PHP worker via `jobs.process` RPC\n3. On failure, retries with exponential backoff (2s, 4s, 8s, ..., max 32s)\n4. After `max_retries` failures, job is discarded and logged\n\n### Push via RPC\n\nThe `jobs.push` RPC method accepts `{queue, payload}` and pushes to the configured driver. This is how `FolkQueue` (Laravel) and `RpcClient` (SDK) submit jobs without knowing the backend.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolk-project%2Ffolk-plugin-jobs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffolk-project%2Ffolk-plugin-jobs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolk-project%2Ffolk-plugin-jobs/lists"}