{"id":31844638,"url":"https://github.com/soderlind/all-sites-cron","last_synced_at":"2025-10-12T07:46:42.647Z","repository":{"id":263615403,"uuid":"890938452","full_name":"soderlind/all-sites-cron","owner":"soderlind","description":"Run wp-cron on all public sites in a multisite network","archived":false,"fork":false,"pushed_at":"2025-10-08T11:09:20.000Z","size":435,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-08T13:15:48.862Z","etag":null,"topics":["wordpress-cron","wordpress-multisite"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soderlind.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://paypal.me/PerSoderlind"}},"created_at":"2024-11-19T12:55:37.000Z","updated_at":"2025-10-08T12:56:48.000Z","dependencies_parsed_at":"2024-11-19T14:37:15.401Z","dependency_job_id":"142bdfd8-8d41-4e3b-a056-8db9c1eacd14","html_url":"https://github.com/soderlind/all-sites-cron","commit_stats":null,"previous_names":["soderlind/dss-cron","soderlind/all-sites-cron"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/soderlind/all-sites-cron","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fall-sites-cron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fall-sites-cron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fall-sites-cron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fall-sites-cron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soderlind","download_url":"https://codeload.github.com/soderlind/all-sites-cron/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soderlind%2Fall-sites-cron/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279010676,"owners_count":26084785,"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-12T02:00:06.719Z","response_time":53,"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":["wordpress-cron","wordpress-multisite"],"created_at":"2025-10-12T07:46:39.067Z","updated_at":"2025-10-12T07:46:42.639Z","avatar_url":"https://github.com/soderlind.png","language":"PHP","readme":"# All Sites Cron\n\nRun wp-cron on all public sites in a multisite network ([REST API based](#benefits-of-rest-mode)).\n\n\u003e \"You could have done this with a simple cron job. Why use this plugin?\" \n\u003e \n\u003e I have a cluster of WordPress sites. I did run a shell script calling wp cli, but the race condition was a problem. I needed a way to run wp-cron on all sites without overlapping. This plugin was created to solve that problem.\n\n## 🚀 Quick Start\n\n1. Download [`all-sites-cron.zip`](https://github.com/soderlind/all-sites-cron/releases/latest/download/all-sites-cron.zip)\n2. Upload via `Network \u003e Plugins \u003e Add New \u003e Upload Plugin`\n3. Network Activate the plugin.\n4. Disable WordPress default cron in `wp-config.php`:\n   ```php\n   define( 'DISABLE_WP_CRON', true );\n   ```\n\nAlso available via Composer:\n\n```bash\ncomposer require soderlind/all-sites-cron\n```\n\n**Updates**\n   * Plugin [updates are handled automatically](https://github.com/soderlind/wordpress-plugin-github-updater#readme) via GitHub. No need to manually download and install updates.\n\n## 🔧 Configuration\n\nThe plugin exposes a REST API route that triggers cron across your network.\n\nJSON usage:\n\n```\nhttps://example.com/wp-json/all-sites-cron/v1/run\n```\n\nGitHub Actions plain text (add `?ga=1`):\n\n```\nhttps://example.com/wp-json/all-sites-cron/v1/run?ga=1\n```\n\n[Deferred mode](DEFERRED-MODE.md) (add `?defer=1` - responds immediately, processes in background):\n\n```\nhttps://example.com/wp-json/all-sites-cron/v1/run?defer=1\n```\n\n**🚀 Redis Queue Support**: If Redis is available, deferred mode automatically uses Redis for job queuing (more reliable and scalable). See [Redis Queue documentation](REDIS-QUEUE.md) or [Quick Start](REDIS-QUICK-START.md).\n\nCombine parameters (GitHub Actions + Deferred):\n\n```\nhttps://example.com/wp-json/all-sites-cron/v1/run?ga=1\u0026defer=1\n```\n\nAdding `?ga=1` outputs results in GitHub Actions compatible format:\n\n- Success: `::notice::Running wp-cron on X sites`\n- Error: `::error::Error message`\n\n\u003cdetails\u003e\n\n  \u003csummary\u003e\u003cstrong\u003eExample GitHub Action success notice\u003c/strong\u003e\u003c/summary\u003e\n\n  \u003cimg src=\"assets/ga-output.png\" alt=\"GitHub Action - Success notice\" style=\"with: 60%\"\u003e\n\u003c/details\u003e\n\n## ⏰ Trigger Options\n\n1. (Preferred) Use a service like cron-job.org, pingdom.com, or easycron.com to call the endpoint every 5 minutes.\n\n2. System Crontab (every 5 minutes):\n\n```bash\n*/5 * * * * curl -s https://example.com/wp-json/all-sites-cron/v1/run\n```\n\n3. GitHub Actions every 5 minutes. (5 minutes is the [shortest interval in GitHub Actions](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule)):\n\n```yaml\nname: All Sites Cron Job\non:\n  schedule:\n    - cron: '*/5 * * * *'\n\nenv:\n  CRON_ENDPOINT: 'https://example.com/wp-json/all-sites-cron/v1/run?ga=1\u0026defer=1'\n\njobs:\n  trigger_cron:\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - run: |\n          curl -X GET ${{ env.CRON_ENDPOINT }} \\\n            --connect-timeout 10 \\\n            --max-time 30 \\\n            --retry 3 \\\n            --retry-delay 5 \\\n            --silent \\\n            --show-error \\\n            --fail\n```\n\n**Note:** Using `defer=1` is recommended for GitHub Actions to prevent timeout errors on large networks.\n\n## Customization\n\n### Filters\n\nThe plugin provides several filters to customize its behavior:\n\n#### `all_sites_cron_rate_limit_seconds`\n\nControl the cooldown period between cron runs to prevent overlapping executions.\n\n- **Type**: `int`\n- **Default**: `60` (seconds)\n- **Legacy**: `dss_cron_rate_limit_seconds` (still supported)\n\n```php\nadd_filter( 'all_sites_cron_rate_limit_seconds', function( $seconds ) {\n    return 120; // 2 minutes between runs\n});\n```\n\n#### `all_sites_cron_number_of_sites`\n\nSet the maximum number of sites to process in total per request.\n\n- **Type**: `int`\n- **Default**: `1000`\n- **Legacy**: `dss_cron_number_of_sites` (still supported)\n\n```php\nadd_filter( 'all_sites_cron_number_of_sites', function( $max_sites ) {\n    return 500; // Process up to 500 sites\n});\n```\n\n#### `all_sites_cron_batch_size`\n\nControl how many sites are processed in each batch. Smaller batches use less memory.\n\n- **Type**: `int`\n- **Default**: `50`\n- **New in**: v1.3.0\n\n```php\nadd_filter( 'all_sites_cron_batch_size', function( $batch_size ) {\n    return 25; // Process 25 sites per batch\n});\n```\n\n#### `all_sites_cron_request_timeout`\n\nSet the timeout for wp-cron HTTP requests to each site. Uses \"fire and forget\" (non-blocking) requests.\n\n- **Type**: `float`\n- **Default**: `0.01` (10 milliseconds)\n- **Legacy**: `dss_cron_request_timeout` (still supported)\n\n```php\nadd_filter( 'all_sites_cron_request_timeout', function( $timeout ) {\n    return 0.05; // 50 milliseconds\n});\n```\n\n#### `https_local_ssl_verify`\n\nWordPress core filter to control SSL verification for local requests.\n\n- **Type**: `bool`\n- **Default**: `false` (in plugin context)\n- **Core Filter**: This is a WordPress core filter\n\n```php\nadd_filter( 'https_local_ssl_verify', function( $verify ) {\n    return true; // Enable SSL verification\n});\n```\n\n### Filter Usage Examples\n\n**Large Network Configuration** (1000+ sites):\n\n```php\n// Process more sites in smaller batches\nadd_filter( 'all_sites_cron_number_of_sites', fn() =\u003e 2000 );\nadd_filter( 'all_sites_cron_batch_size', fn() =\u003e 25 );\nadd_filter( 'all_sites_cron_rate_limit_seconds', fn() =\u003e 180 ); // 3 minutes\n```\n\n**Small Network Configuration** (\u003c 100 sites):\n\n```php\n// Faster processing with larger batches\nadd_filter( 'all_sites_cron_batch_size', fn() =\u003e 100 );\nadd_filter( 'all_sites_cron_rate_limit_seconds', fn() =\u003e 30 ); // 30 seconds\n```\n\n**Development/Testing Configuration**:\n\n```php\n// More aggressive settings for testing\nadd_filter( 'all_sites_cron_rate_limit_seconds', fn() =\u003e 10 ); // 10 seconds\nadd_filter( 'all_sites_cron_batch_size', fn() =\u003e 5 );\nadd_filter( 'all_sites_cron_request_timeout', fn() =\u003e 0.1 );\n```\n\n### Legacy Filters\n\nThe following legacy filters from the \"DSS Cron\" plugin are still supported but deprecated:\n\n- `dss_cron_rate_limit_seconds` → Use `all_sites_cron_rate_limit_seconds`\n- `dss_cron_number_of_sites` → Use `all_sites_cron_number_of_sites`\n- `dss_cron_request_timeout` → Use `all_sites_cron_request_timeout`\n- `dss_cron_sites_transient` → No longer used (removed in v1.3.0)\n\n**Migration**: Update your code to use the new `all_sites_cron_*` filter names. Legacy filters will be removed in a future major version.\n\n### Interpreting Rate Limiting\n\nIf called again before the cooldown finishes the API returns HTTP 429 with JSON:\n\n```json\n{\n  \"success\": false,\n  \"error\": \"rate_limited\",\n  \"message\": \"Rate limited. Try again in 37 seconds.\",\n  \"retry_after\": 37,\n  \"cooldown\": 60,\n  \"last_run_gmt\": 1696071234,\n  \"timestamp\": \"2025-09-30 12:35:23\"\n}\n```\n\nHeaders include: `Retry-After: \u003cseconds\u003e`.\n\n\n## Benefits of REST mode\n\n- No rewrite rules to flush: activation is simpler and avoids edge cases with 404s or delayed availability.\n- No unexpected 301 canonical/trailing‑slash redirects: direct, cache‑friendly 200 responses.\n- Versioned, discoverable endpoint (`/wp-json/all-sites-cron/v1/run`) integrates with the WP REST index and tooling.\n- Consistent structured JSON by default plus optional GitHub Actions text via `?ga=1`.\n- Proper HTTP status codes (e.g. 429 for rate limiting, 400 for invalid context) instead of a blanket 200.\n- Easy extensibility: future endpoints (status, logs, defer mode, auth) can be added under the same namespace without new rewrites.\n- Reduced theme / front‑end interference: bypasses template loading and front‑end filters tied to `template_redirect`.\n- Better compatibility with CDNs and monitoring: REST semantics and headers are predictable and cache‑aware.\n- Straightforward integration in external systems (CI/CD, orchestration) that already speak JSON.\n- Built‑in argument handling and potential for schema/permission hardening via `permission_callback`.\n- Clean separation of concerns: routing (REST) vs. execution logic (cron dispatcher) improves maintainability.\n- Clear place to implement enhancements (rate limiting, future defer/background mode, auth tokens, metrics) with minimal risk.\n- Easier automated testing using WP REST API test utilities (no need to simulate front‑end rewrite resolution).\n- Avoids canonical redirect filter hacks previously needed to suppress 301s on `/dss-cron`.\n- Safer for multi‑environment deployments (no dependency on rewrite flush timing during deploy pipelines).\n\n## Copyright and License\n\nAll Sites Cron is copyright 2024 Per Soderlind\n\nAll Sites Cron is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.\n\nAll Sites Cron is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nYou should have received a copy of the GNU Lesser General Public License along with the Extension. If not, see http://www.gnu.org/licenses/.\n\n---\n\n### Migration Note\n\nThe plugin was renamed from \"DSS Cron\" (slug: `dss-cron`) to \"All Sites Cron\" (slug: `all-sites-cron`). The old REST namespace `dss-cron/v1` is still registered for backward compatibility, but you should migrate your automation scripts to use `all-sites-cron/v1`. Legacy WordPress filters like `dss_cron_number_of_sites` continue to work; new code should use the `all_sites_cron_*` equivalents.\n","funding_links":["https://paypal.me/PerSoderlind"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoderlind%2Fall-sites-cron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoderlind%2Fall-sites-cron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoderlind%2Fall-sites-cron/lists"}