VOOZH about

URL: https://deepwiki.com/hypervel/console/7.2-event-execution-and-lifecycle

⇱ Event Execution and Lifecycle | hypervel/console | DeepWiki


Loading...
Menu

Event Execution and Lifecycle

Purpose and Scope

This document provides a comprehensive reference for the Event class, the most critical component in the scheduling system (importance rating: 9.54). The Event class represents a scheduled task and manages its complete execution lifecycle, including eligibility checks, execution modes, callback management, output handling, and concurrency control through mutexes.

For information about defining schedule frequencies and cron expressions, see Defining Schedule Frequencies. For concurrency control mechanisms and mutex contracts, see Concurrency and Mutex Management. For the scheduler daemon that executes events, see Running the Scheduler.


Event Lifecycle Overview

The execution lifecycle of an event follows a multi-stage pipeline with several checkpoint gates. Understanding this flow is critical for implementing custom behavior and debugging scheduling issues.


Event Execution Lifecycle State Machine - Shows the complete flow from eligibility checking through execution to cleanup. The event must pass multiple gates (isDue, filtersPass, shouldSkipDueToOverlapping) before execution begins. Exceptions trigger immediate mutex cleanup to prevent deadlocks.

Sources: src/Scheduling/Event.php111-124 src/Scheduling/Event.php129-133 src/Scheduling/Event.php156-167 src/Scheduling/Event.php213-222


Execution Flow

Entry Point: run()

The run() method is the main entry point for event execution, called by the scheduler daemon when an event is eligible to execute.


run() Method Flow - The entry point orchestrates three main phases: starting (with overlap check), output writing, and finishing. If overlap is detected, execution is skipped entirely.

The method signature and implementation:

MethodParametersReturn TypeDescription
run()Container $containermixedMain execution entry point

Sources: src/Scheduling/Event.php111-124

Overlap Prevention

Before execution begins, the event checks if another instance is currently running when withoutOverlapping is enabled.


Overlap Detection Flow - Uses the EventMutex contract to attempt lock creation. If the lock cannot be created, another instance is running and execution should be skipped.

Sources: src/Scheduling/Event.php129-133

Starting Execution

The start() method initiates execution by calling before callbacks and then executing the command, with exception handling to ensure mutex cleanup.


start() Method Sequence - Demonstrates the try-catch pattern that ensures mutex cleanup even when exceptions occur. All before callbacks receive dependency injection via the container.

Sources: src/Scheduling/Event.php156-167 src/Scheduling/Event.php227-232

Command Execution

The execute() method dispatches to one of two execution modes based on the isSystem property.


execute() Execution Mode Dispatch - System commands run as shell processes via Symfony Process component, while console commands execute through the Hyperf kernel. Process instances are stored in Context for output retrieval.

Execution ModeClass/ComponentDescription
System CommandSymfony\Component\Process\ProcessExecutes shell commands in separate process
Console CommandKernelContract::call()Executes registered Hyperf console commands

Sources: src/Scheduling/Event.php172-180 src/Scheduling/Event.php185-196

System Command Execution Details

For system commands (isSystem=true), the event creates a Symfony Process instance and stores it in the context for later output retrieval.


System Command Process Flow - The Process is created from the command string, stored in Context with a key based on the mutex name, then executed. This Context storage enables output retrieval after execution.

Sources: src/Scheduling/Event.php185-196 src/Scheduling/Event.php201-208

Finishing and Cleanup

The finish() method stores the exit code, executes after callbacks, and removes the mutex lock in a finally block to ensure cleanup.


finish() Cleanup Sequence - Uses a try-finally block to guarantee mutex removal regardless of callback success or failure. This prevents deadlocks from failed callbacks.

Sources: src/Scheduling/Event.php213-222 src/Scheduling/Event.php237-242 src/Scheduling/Event.php732-737


Callback System

The Event class provides a comprehensive callback system that allows execution at different lifecycle points, with support for conditional execution and output capture.

Callback Registration Methods


Callback Registration Architecture - All callbacks are stored in either beforeCallbacks or afterCallbacks arrays. The system provides multiple registration methods that wrap callbacks with conditional logic or output handling.

Sources: src/Scheduling/Event.php56-61 src/Scheduling/Event.php552-557 src/Scheduling/Event.php570-581

Before Callbacks

Before callbacks execute prior to command execution and receive full dependency injection from the container.

MethodParametersDescription
before()Closure $callbackRegister callback to run before execution
pingBefore()string $urlHTTP GET request before execution
pingBeforeIf()bool $value, string $urlConditional ping before execution

Sources: src/Scheduling/Event.php552-557 src/Scheduling/Event.php458-469

After Callbacks

After callbacks execute after command completion, regardless of success or failure. They can optionally receive the command output.


then() Method Intelligence - Uses reflection to detect if the callback expects a Stringable $output parameter. If so, automatically converts to an output-aware callback.

MethodParametersDescription
after() / then()Closure $callbackRegister callback after execution
thenWithOutput()Closure $callback, bool $onlyIfOutputExistsCallback receives command output

Sources: src/Scheduling/Event.php562-581 src/Scheduling/Event.php586-591

Success and Failure Callbacks

Conditional callbacks execute based on the exit code stored during the finish() phase.


Conditional Callback Execution - Success and failure callbacks wrap the user callback in a conditional check against the exitCode property set during finish().

MethodParametersDescription
onSuccess()Closure $callbackExecute if exitCode === 0
onSuccessWithOutput()Closure $callback, bool $onlyIfOutputExistsExecute if success, with output
onFailure()Closure $callbackExecute if exitCode !== 0
onFailureWithOutput()Closure $callback, bool $onlyIfOutputExistsExecute if failure, with output

Sources: src/Scheduling/Event.php596-609 src/Scheduling/Event.php624-637 src/Scheduling/Event.php614-619 src/Scheduling/Event.php642-647

Output-Aware Callbacks

Output-aware callbacks receive the command output as a Stringable parameter, with automatic output capture configuration.


Output-Aware Callback Flow - The withOutputCallback() wrapper reads the output file and passes it as a Stringable instance to the user callback. If onlyIfOutputExists is true and output is empty, the callback is skipped.

Sources: src/Scheduling/Event.php586-591 src/Scheduling/Event.php614-619 src/Scheduling/Event.php642-647 src/Scheduling/Event.php652-661

HTTP Ping Callbacks

The event system provides built-in HTTP ping functionality for health check and monitoring integrations.


HTTP Ping Callback Architecture - All ping methods use the same pingCallback() helper that resolves an HTTP client from the container, makes a GET request, and reports any exceptions to the exception handler without interrupting the callback chain.

HTTP Client Resolution Strategy:

  1. Check for HttpClientInterface binding in container
  2. Check for HttpClient binding in container
  3. Create default HttpClient with 10s connect timeout and 30s total timeout
MethodTimingDescription
pingBefore()Before executionPing before command runs
thenPing()After executionPing after command completes
pingOnSuccess()After successPing if exitCode === 0
pingOnFailure()After failurePing if exitCode !== 0

Sources: src/Scheduling/Event.php458-517 src/Scheduling/Event.php522-547


Output Management

The Event class provides comprehensive output capture and routing capabilities, supporting file output, email delivery, and programmatic access.

Output Capture Configuration


Output Configuration Flow - Multiple methods can trigger output capture. The ensureOutputIsBeingCaptured() method automatically configures a default log file if no output destination is specified.

PropertyTypeDefaultDescription
output?stringnullFile path for output destination
shouldAppendOutputboolfalseWhether to append or overwrite
ensureOutputIsBeingCapturedboolfalseFlag indicating output is being captured

Sources: src/Scheduling/Event.php44-51 src/Scheduling/Event.php88 src/Scheduling/Event.php314-331 src/Scheduling/Event.php419-425

File Output Writing

The writeOutput() method is called after execution to persist command output to the configured file.


writeOutput() Execution Sequence - Output is only written if configured. The method retrieves output differently based on whether the event is a system command or console command, then uses the Filesystem service to write or append.

Output Retrieval Methods:

Execution ModeMethodSource
System CommandgetProcessOutput()Context::get("scheduling_process:{mutexName}")
Console Commandkernel->output()KernelContract buffered output

Sources: src/Scheduling/Event.php336-350 src/Scheduling/Event.php355-362 src/Scheduling/Event.php201-208

Email Output Delivery

The event system can automatically email command output to specified recipients using the Mailer contract.


Email Output Architecture - Email methods automatically configure output capture and register callbacks that read the output file and send it via the Mailer. The subject line uses the event description or command string.

Email Subject Line Generation:

  1. If description property is set, use it as subject
  2. Otherwise, use format: "Scheduled Job Output For [{command}]"

Sources: src/Scheduling/Event.php377-414 src/Scheduling/Event.php430-453


Execution Modes

The Event class supports two distinct execution modes, determined by the isSystem property set during construction.

Execution Mode Comparison

AspectConsole Command ModeSystem Command Mode
isSystem valuefalsetrue
Execution methodKernelContract::call()Process::fromShellCommandline()
Output captureKernel buffered outputProcess output stream
Working directoryN/AApplication base path
Context storageNoYes (scheduling_process:{mutexName})
DependenciesHyperf/Hypervel kernelSymfony Process component

Sources: src/Scheduling/Event.php83 src/Scheduling/Event.php172-180

Console Command Execution

Console commands execute through the Hyperf kernel's call() method, which provides dependency injection and output buffering.


Console Command Execution Flow - The kernel handles command parsing, instance resolution from the container, dependency injection, and output buffering. The command string format can include arguments and options.

Example command strings:

  • "inspire"
  • "user:create --name=John --email=john@example.com"
  • "queue:work redis --tries=3"

Sources: src/Scheduling/Event.php178-179

System Command Execution

System commands execute as shell processes using Symfony's Process component, providing access to any executable on the system.


System Command Process Flow - Creates a Symfony Process from the shell command string with the application base path as working directory. The Process instance is stored in Context for later output retrieval.

Context Key Format: "scheduling_process:{mutexName}"

This allows the getProcessOutput() method to retrieve the Process instance and access its output after execution completes.

Example system commands:

  • "php artisan migrate --force"
  • "curl -s https://example.com/health"
  • "/usr/local/bin/backup.sh --full"

Sources: src/Scheduling/Event.php185-196 src/Scheduling/Event.php201-208


Event Eligibility

Before an event can execute, it must pass several eligibility checks. The scheduler calls these methods in sequence to determine if an event should run.

Eligibility Check Pipeline


Event Eligibility Pipeline - Shows the complete evaluation sequence. The event must pass maintenance mode, cron expression, environment, custom filters, and overlap checks before execution.

Sources: src/Scheduling/Event.php247-255 src/Scheduling/Event.php292-309

Cron Expression Evaluation

The isDue() method checks if the event's cron expression matches the current time, accounting for timezone and maintenance mode.


isDue() Evaluation Sequence - The method performs three checks: maintenance mode, cron expression matching with timezone support, and environment restriction. All must pass for the event to be considered due.

Sources: src/Scheduling/Event.php247-255 src/Scheduling/Event.php260-263 src/Scheduling/Event.php268-278 src/Scheduling/Event.php283-287

Custom Filter Evaluation

The filtersPass() method evaluates user-defined filter and reject callbacks, updating the lastChecked timestamp for repeatable event tracking.


filtersPass() Logic Flow - First updates lastChecked timestamp, then evaluates filters (callbacks that must return true) and rejects (callbacks that must return false). All callbacks receive dependency injection via app->call().

Filter Callback Semantics:

Callback TypeArray PropertyMust ReturnEffect if Condition Met
Filter$filterstrueContinue evaluation
Filter$filtersfalseSkip event (filter rejected)
Reject$rejectsfalseContinue evaluation
Reject$rejectstrueSkip event (reject matched)

Sources: src/Scheduling/Event.php292-309

Repeatable Events

Events can be configured to repeat multiple times per minute using the repeatSeconds property. The eligibility system tracks when the event was last checked to enforce the repeat interval.


Repeatable Event Logic - The isRepeatable() check determines if the event is configured for sub-minute repeats. The shouldRepeatNow() check ensures enough time has passed since the last check based on the repeatSeconds interval.

PropertyTypeDefaultDescription
repeatSeconds?intnullInterval in seconds for sub-minute repeats
lastChecked?CarbonnullTimestamp of last eligibility check

Sources: src/Scheduling/Event.php138-149 src/Scheduling/Event.php73


Mutex Integration

The Event class integrates with the EventMutex contract to prevent overlapping executions and coordinate single-server execution in distributed deployments.

Mutex Name Generation

Each event generates a unique mutex name used as the lock identifier in the mutex implementation.


Mutex Name Generation Logic - If a custom resolver is configured via createMutexNameUsing(), it takes precedence. Otherwise, the default name is generated by hashing the cron expression and command string.

Default Mutex Name Format:

framework/schedule-{sha1(expression + command)}

Example: For an event with expression "0 * * * *" and command "inspire", the mutex name would be:

framework/schedule-7f8c6e9a2b4d5e1f3a8c9d2e5f4a7b8c6d9e2f5a

Sources: src/Scheduling/Event.php705-715 src/Scheduling/Event.php66

Mutex Name Customization

Events can customize their mutex name generation using a string or closure resolver.


Custom Mutex Name Resolver - Accepts either a static string (wrapped in a closure) or a dynamic closure that receives the Event instance. This enables advanced locking strategies based on event properties.

Example use cases for custom mutex names:

  • Group multiple events under the same lock
  • Include dynamic parameters in the lock key
  • Use different locking strategies per environment

Sources: src/Scheduling/Event.php720-727

Overlap Prevention Workflow

The overlap prevention system uses the mutex to ensure only one instance of an event executes at a time.


Overlap Prevention Sequence - The mutex is created before execution starts and removed during cleanup in the finish() method's finally block. This ensures the lock is always released, even if execution fails.

Mutex Lifecycle:

  1. Check - shouldSkipDueToOverlapping() attempts to create mutex
  2. Execute - If successful, event runs normally
  3. Cleanup - removeMutex() called in finally block of finish()

Sources: src/Scheduling/Event.php129-133 src/Scheduling/Event.php213-222 src/Scheduling/Event.php732-737

Mutex Implementation Configuration

Events can use custom mutex implementations for specialized locking strategies.


Mutex Configuration Architecture - The mutex is injected during Event construction but can be replaced using preventOverlapsUsing(). All mutex implementations must implement the EventMutex contract with create(), exists(), and forget() methods.

Sources: src/Scheduling/Event.php96-104 src/Scheduling/Event.php695-700


Integration Points

The Event class integrates with multiple framework components and external libraries to provide its functionality.

Container Integration

The Event class relies heavily on the container for dependency resolution and callback execution.


Container Integration Points - The Event uses get() to resolve services, call() to execute callbacks with dependency injection, and passes the container to various methods for downstream resolution.

MethodContainer MethodPurpose
execute()get(KernelContract::class)Resolve kernel for console commands
writeOutput()get(Filesystem::class)Resolve filesystem for output writing
callBeforeCallbacks()call($callback)Execute callbacks with DI
callAfterCallbacks()call($callback)Execute callbacks with DI
filtersPass()call($callback) (via app)Execute filter callbacks with DI
pingCallback()get(ExceptionHandler::class)Resolve exception handler for errors

Sources: src/Scheduling/Event.php111-124 src/Scheduling/Event.php178-179 src/Scheduling/Event.php227-232 src/Scheduling/Event.php237-242 src/Scheduling/Event.php336-350

Kernel Integration

Console commands execute through the KernelContract, which provides command parsing, execution, and output buffering.


Kernel Integration Sequence - The kernel handles command execution and maintains an output buffer that can be retrieved after execution. This enables the Event to capture console output for writing to files or emailing.

Sources: src/Scheduling/Event.php178-179 src/Scheduling/Event.php361

Context Storage Integration

System commands use the Hypervel Context system to store Process instances for later output retrieval.


Context Storage Pattern - The Process instance is stored during runProcess() and retrieved during getProcessOutput() using a key based on the event's mutex name. This allows the process to be accessed after execution completes.

Context Key: "scheduling_process:{mutexName}"

This pattern ensures each event's process is uniquely identifiable and can be retrieved even if multiple events execute concurrently.

Sources: src/Scheduling/Event.php193 src/Scheduling/Event.php203

Exception Handling Integration

The Event class integrates with the ExceptionHandler contract for reporting HTTP ping failures and other errors.


Exception Handling for HTTP Pings - The ping callback catches HTTP client exceptions and reports them to the exception handler without interrupting the callback chain or failing the event.

This ensures that transient network failures or unreachable URLs don't cause scheduled tasks to fail.

Sources: src/Scheduling/Event.php524-530

External Library Dependencies

The Event class integrates with several external libraries for core functionality.

LibraryPurposeUsage in Event
dragonmantank/cron-expressionCron expression parsingexpressionPasses() evaluates cron expressions
guzzlehttp/guzzleHTTP clientpingCallback() makes GET requests
symfony/processProcess executionrunProcess() executes system commands
carbon/carbonDate/time handlingnextRunDate(), lastChecked timestamps
hyperf/stringableString wrapperOutput passed to callbacks as Stringable
hyperf/supportFilesystem operationswriteOutput() writes/appends files

Sources: src/Scheduling/Event.php9-33


Summary

The Event class is the core component of the scheduling system, managing the complete lifecycle of scheduled tasks from eligibility checking through execution to cleanup. Key architectural patterns include:

  • Multi-stage eligibility pipeline with cron, environment, filter, and mutex checks
  • Dual execution modes supporting both console commands and system processes
  • Comprehensive callback system with before/after hooks, conditional callbacks, and output-aware callbacks
  • Flexible output management supporting file output, email delivery, and programmatic access
  • Mutex-based concurrency control preventing overlapping executions and coordinating multi-server deployments
  • Deep container integration enabling dependency injection throughout the execution lifecycle
  • Context-based process storage for retrieving system command output

The Event class coordinates with multiple framework contracts (EventMutex, KernelContract, ExceptionHandler) and external libraries (Symfony Process, Guzzle HTTP, Cron Expression) to provide a robust, production-ready scheduling solution.

Sources: src/Scheduling/Event.php1-738

Refresh this wiki

On this page