Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cron Manager Bundle Laravel Package

phakpoom/cron-manager-bundle

A PHP bundle for managing cron jobs: register scheduled tasks, review their timing, and keep cron-driven work organized from one place. Useful when you want a lightweight, centralized way to declare and inspect recurring jobs instead of scattering crontab entries across servers.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Verdict up front: this is not a Laravel package. phakpoom/cron-manager-bundle is a Symfony2 bundle (BCCCronManagerBundle) — the name, the repo, and the *Bundle convention all confirm it. Treat any Laravel integration as a greenfield port with attribution, not an install-and-configure exercise. The package's real value is as a reference design for DB-backed cron management, not as a dependency.

Architecture fit

  • The package targets Symfony 2.x conventions: a Bundle subclass, a DependencyInjection/*Extension, Resources/config/services.yml, Twig templates under Resources/views, and almost certainly Doctrine ORM entities for the cron table. None of these have a Laravel analog — Laravel has no bundle bootstrapping, no DI compiler passes, no Twig by default.
  • Laravel does share Symfony components (symfony/console, symfony/process, symfony/http-foundation), so the execution layer — spawning processes, capturing exit codes/output — is conceptually portable. The framework plumbing around it is not.
  • Net: the durable, reusable asset is the domain model (cron table schema, schedule expression handling, enable/disable semantics, run history, output capture). Everything else is throwaway.

Integration feasibility: Low (as a dependency) / Moderate (as a rewrite)

  • Composer install into a Laravel app is technically possible but functionally inert: nothing registers the bundle, so you get autoloaded classes and zero behavior. The symfony/framework-bundle and doctrine/orm transitive requirements would drag an entire parallel framework into vendor/ for no runtime benefit.
  • A faithful reimplementation is realistic in scope — cron managers of this class are typically a few hundred to ~1.5k lines: a schema, an expression parser or CRUD form, a due-job selector, a process runner, and a list/detail UI. A competent Laravel engineer should scope this at 1–2 weeks including tests, UI, and locking. That is the honest "integration cost."

Technical risk: High

  • Abandonment risk. 0 stars, 0 dependents, 0 forks-worth-of-signal. There is no upstream to merge into, no issue triage, no security response. The 2024-04-04 release date is almost certainly a Packagist metadata/tag artifact, not evidence of maintenance — the code targets Symfony 2, which has been EOL since 2018.
  • Platform EOL. Symfony 2.x implies PHP 5.x–7.x-era idioms. Expect each(), untyped properties, possibly mcrypt, and no PHP 8.x verification. You are adopting unpatched, unaudited code if you copy it verbatim.
  • Security surface. A cron manager is, by construction, remote command execution driven by database rows. Any design that concatenates stored strings into a shell invocation is a privilege-escalation path for anyone with write access to that table (SQL injection elsewhere in the app, a compromised admin panel, or a leaked DB backup). This must be audited line-by-line before any code is lifted.
  • Doctrine coupling. Entities, repositories, and annotations/XML mappings are Laravel-hostile and will not translate mechanically to Eloquent.
  • Unknown test coverage. With no CI signal and no dependents, assume zero tests. Any ported logic is unverified logic.
  • License is clean (MIT), so forking and vendoring is legally straightforward — provided you preserve the copyright notice. That is the one unambiguous positive here.

Key questions to resolve before committing

  1. Is the actual requirement "let ops edit crontab from a UI," or "replace cron with an in-app scheduler"? Laravel's built-in scheduler + schedule:run may satisfy 80% of the need with zero new code.
  2. Does the business need per-job run history, output capture, and manual trigger? If yes, that's the genuine gap Laravel doesn't fill and justifies building.
  3. Is the deployment single-node or horizontally scaled? This determines whether distributed locking is a hard requirement (it usually is, and this package predates that concern).
  4. Who owns the ported code long-term, and is there appetite to maintain an internal fork with no upstream?
  5. Are there compliance/audit constraints on who may define shell commands (SOC2, PCI)? If so, the free-text command field is a blocker regardless of framework.
  6. Does the existing app already have a job-queue worker (Horizon/Redis)? If so, "cron" may be the wrong primitive entirely.

Scoring: as a dependency, 0/10 — wrong framework, unmaintained, zero ecosystem. As a design reference, 3/10 — the schema and CRUD shape are mildly instructive, but any competent engineer would arrive at a similar design unaided.

Integration Approach

Stack fit: poor as published, workable as a port

  • Nothing in the package assumes Laravel, and nothing in Laravel assumes bundles. There is no adapter layer that makes this clean.
  • The one genuine overlap is the process-execution primitive: if the bundle shells out via symfony/process, that class is already a transitive Laravel dependency and can be used unmodified in the port.
  • The UI (Twig + likely Bootstrap 3-era markup) should be discarded entirely and rebuilt in Blade + the app's existing component library (Filament, Nova, Livewire, or plain Blade). Porting Twig markup costs more than rewriting it.

Migration path (fork-and-reimplement, not lift-and-shift)

  1. Vendor/attribute. Fork to an internal namespace (e.g. App\Cron or a private acme/laravel-cron-manager). Preserve the MIT copyright notice. Do not depend on the upstream repo — it can disappear.
  2. Extract the domain, not the code. Read the Symfony source to recover: the table schema (columns for expression, command, enabled flag, last/next run, output, exit code), the due-selection query, and any expression-matching logic. Re-express these as a Laravel migration + Eloquent model + query scope.
  3. Replace the Symfony shell with Laravel primitives:
    • Bundle/DI extension → a ServiceProvider registering bindings and a CronManager singleton.
    • Symfony console command → php artisan cron:run (or a CronRunCommand), scheduled every minute via routes/console.php / Kernel::schedule.
    • Doctrine entity + repository → Eloquent model + query builder.
    • Twig views + Symfony controllers → Blade views + resourceful controllers + policies for authorization.
  4. Do not build a second scheduler. Prefer one of two postures: (a) DB-driven runner — artisan command reads enabled rows, evaluates due-ness, dispatches; or (b) scheduler-adjacent — keep Schedule::command() as the source of truth and use the DB table only for enable/disable toggles and run history. Posture (b) has a dramatically smaller blast radius and is usually the right call.
  5. Wrap every execution in a lock. Cache::lock("cron:{$job->id}", 300)->get() or withoutOverlapping(). This is non-negotiable and is the single most common defect in ported cron managers.

Compatibility matrix to target

Concern Target Notes
PHP 8.1 / 8.2 / 8.3 Original likely 5.x–7.x; do not carry untyped code forward
Laravel 10.x / 11.x / 12.x Service provider + Artisan + Eloquent; no Symfony kernel
Database MySQL 8 / Postgres 14+ Row-level locking for due-job selection (SELECT … FOR UPDATE SKIP LOCKED on PG)
Process symfony/process (already transitively present) Avoid shell_exec/exec string concatenation
UI Blade + app's component library Discard Twig assets
Removed deps symfony/framework-bundle, doctrine/orm, Twig Must not enter composer.json

Sequencing (suggested 3 sprints, ~4–6 weeks with one engineer incl. review)

  • Sprint 1 — Decide & de-risk. Confirm the requirement against native Schedule. If building is justified, complete a security review of the read-only Symfony source to harvest schema and semantics. Deliverable: ADR documenting build-vs-buy-vs-native, plus extracted schema.
  • Sprint 2 — Core. Migration, model, cron:run command, locking, run-history table, output capture with truncation limits, exit-code recording. Tests against a fake process runner (never shell out in CI). Deliverable: working CLI, feature-flagged off.
  • Sprint 3 — Surface & operate. Blade/Filament CRUD with authorization policies, enable/disable toggles, manual "run now" with confirmation, structured logs and metrics, alerting on missed/overlapping runs. Deliverable: GA behind a flag with a documented rollback (disable the flag → falls back to native Schedule).
  • Cutover. Run the DB-driven runner in shadow mode (log what it would run) for one to two weeks against the existing crontab before switching authority. Never flip the source of truth in a single step.

Operational Impact

Maintenance

  • You are maintaining a permanent internal fork. There is no upstream to rebase onto, no changelog to track, and no CVE feed. Budget roughly 10–15% of one engineer ongoing for dependency bumps, Laravel major-version migrations, and bugfixes — plus a full re-audit at each Laravel upgrade.
  • The upside of forking: the code is small, well-bounded, and lives inside your app, so it inherits your testing, static analysis, and code review. That is a strictly better position than depending on a 0-star package.
  • Add the source repo to a quarterly "unmaintained dependency" review list only if you keep any verbatim code; otherwise treat it as internal and review it on the normal cadence.

Support

  • Zero external support. No maintainer, no community, no Stack Overflow corpus, no commercial backing. Every question is answered internally.
  • Mitigate with: an ADR explaining why the code exists and what it replaced, a runbook covering "how to disable a runaway job" and "how to recover from a stuck lock," and a named owner in the service catalog.
  • If a vendor/agency relationship exists, flag that the package cannot be a support obligation — it must be reclassified as first-party code.

Scaling

  • Single node: trivially fine. One artisan process per minute, sequential or small worker pool.
  • Multi-node: this is the failure mode that kills naive cron managers. Two app servers each running cron:run will double-fire every job unless you have a distributed lock per job and a leader election / single-runner guard for the dispatcher itself. Use Redis or the DB as the lock store — never local files.
  • Throughput: long-running jobs will block the runner and cause schedule drift. Cap concurrency, enforce per-job timeouts (Process::setTimeout), and move anything heavy onto the queue rather than executing inline.
  • Table growth: run-history rows accumulate fast at 1-minute granularity (525k rows/job/year). Plan retention/partitioning from day one — this is omitted from most implementations and becomes a production incident around month six.
  • DB contention: the due-job selector runs every minute; without a proper index on (enabled, next_run_at) it degrades as history grows.

Failure modes to instrument and alert on

  1. Silent non-execution — cron daemon absent, schedule:run not wired into the container, or the scheduler container crashed. Detection: heartbeat/dead-man's-switch alert if no run recorded in N minutes. This is the #1 risk: cron failures are invisible by default.
  2. Duplicate execution — multi-node without locking, or a lock that expires mid-job. Detection: count concurrent runs per job ID.
  3. Orphaned/stuck locks — a killed process leaves a lock held; the job never runs again. Detection: lock age alert; locks must have TTLs.
  4. Command injection / privilege escalation — any path where non-ops roles can write to the command column. Mitigation: restrict the command field to an allowlist or make it read-only in the UI entirely; never interpolate user input into a shell string.
  5. Unbounded output — a chatty job writes megabytes into the DB. Mitigation: hard truncation (e.g. 64KB) plus log-offload.
  6. Timezone/DST drift — expression evaluated in UTC while ops thinks local; jobs skip or double-run at DST boundaries. Mitigation: explicit, displayed, per-job timezone.
  7. Overlap — a job exceeding its interval stacks up copies. Mitigation: withoutOverlapping semantics as default-on.
  8. Credential/env mismatch — the runner executes under a different PHP binary or env than the app. Mitigation: pin the binary path and assert environment in the pre-flight.

Ramp-up

  • For the porting engineer: low-to-moderate. The Symfony source is small and readable; the friction is verifying PHP 8 compatibility and re-deriving Doctrine mappings into Eloquent. Expect 2–3 days purely for source comprehension before writing production code, and require a second reviewer for the shell-execution path regardless of seniority.
  • For ops/on-call: low. The mental model (a table of jobs, a per-minute runner, a history view) matches cron and is intuitive. Budget a 30-minute runbook walkthrough covering disable-job, clear-lock, and read-history, plus a documented rollback to native Schedule.
  • For product/leadership: the key framing is that this is not "adopting a package," it is "commissioning a small internal tool." The 0-star/0-dependent profile means the cost curve is front-loaded and entirely yours; the honest comparison is against Laravel's built-in scheduler (free, supported, insufficient only if you need a UI and run history). Approve on that basis, with the shadow-mode cutover as the risk gate.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator