AlkantarClanX12
Your IP : 216.73.217.24
<?php
/**
* Class CRB_Deferred_Tasks
*
* Deferred task queue for the WordPress admin context.
*
* Manages a best-effort queue of deferred tasks to keep interactive screens responsive
* by postponing non-critical work.
*
* Intended Use:
* - UI hydration and secondary refresh work.
* - Maintenance tasks safe to run on a best-effort basis.
*
* Constraints & Limitations:
* - Tasks must be idempotent and tolerate interruption.
* - Not suitable for long-running jobs or strictly ordered operations.
* - No execution guarantees; designed for opportunistic runs.
*
* Architecture:
* - Tasks are stored via a global key with deterministic IDs.
* - Features fault isolation, execution logging, and zombie task protection.
*
*/
final class CRB_Deferred_Tasks {
/**
* Storage key for persisting tasks in the database.
*/
const STORAGE_KEY = '_background_tasks';
/**
* Storage key for persisting the execution log of the last batch.
*/
const LOG_STORAGE_KEY = '_background_tasks_log';
/**
* Maximum number of execution attempts for tasks with conditional execution (exec_until).
* Prevents infinite loops (Zombie tasks).
*/
const MAX_RETRIES = 5;
/**
* Executes background tasks stored in the queue.
*
* Optionally filters execution to a specific set of tasks provided in the list.
* Returns a structured execution log where each entry is an associative array.
* Saves the execution log to the database for historical reference of the last batch.
*
* @param array<int, string>|null $tasks_to_run A list of Task IDs to be executed.
* If null or empty, all queued tasks are executed.
*
* @return array<string, array<string, mixed>> Log of executed tasks.
* Structure: ['status' => 'executed'|'error'|'aborted', 'result' => mixed, 'output' => string, 'error' => string|null]
*
* @since 8.6.4
*/
public static function launcher( ?array $tasks_to_run = null ): array {
$execution_log = array();
if ( ! $task_list = self::get_all() ) {
// Save empty log to reflect that nothing ran
cerber_update_set( self::LOG_STORAGE_KEY, $execution_log );
return $execution_log;
}
if ( ! empty( $tasks_to_run ) ) {
// Filter the main list to include only keys present in the provided list of IDs
// We flip the list of IDs to use array_intersect_key for efficient hash lookup
$task_list = array_intersect_key( $task_list, array_flip( $tasks_to_run ) );
}
if ( empty( $task_list ) ) {
// Save empty log to reflect that nothing ran after filtering
cerber_update_set( self::LOG_STORAGE_KEY, $execution_log );
return $execution_log;
}
// Orchestration Loop: Delegates specific task processing to a dedicated method
foreach ( $task_list as $task_id => $task_details ) {
$execution_log[ $task_id ] = self::process_single_task( (string) $task_id, $task_details );
}
// Persist the execution log of the current batch
cerber_update_set( self::LOG_STORAGE_KEY, $execution_log );
return $execution_log;
}
/**
* Retrieves all pending background tasks from storage.
*
* @return array<string, array> An associative array where key is Task ID and value is task details.
*
* @since 8.6.4
*/
public static function get_all(): array {
$tasks = cerber_get_set( self::STORAGE_KEY );
if ( ! $tasks || ! is_array( $tasks ) ) {
$tasks = array();
}
return $tasks;
}
/**
* Retrieves the execution log of the last batch run.
*
* @return array<string, array<string, mixed>> The log of the last executed batch.
* Returns an empty array if no log exists or it is invalid.
*
* @since 9.6.12
*/
public static function get_last_execution_log(): array {
$log = cerber_get_set( self::LOG_STORAGE_KEY );
if ( ! $log || ! is_array( $log ) ) {
return array();
}
return $log;
}
/**
* Adds a new background task to the execution queue.
*
* Uses deterministic ID generation to prevent duplicates even if parameter order varies.
* It constructs a strictly typed task structure to avoid garbage data.
* Restricts callbacks to strings or static methods (array of strings) for safe serialization.
*
* @param callable|string|array $callback The function or method to be executed.
* Must be a string or a static method array ['Class', 'Method'].
* Closures and Object instances are NOT allowed.
* @param array $task_options Configuration for the task.
* Supported keys:
* - 'args': (array) Parameters to pass to the callback.
* - 'load_admin': (bool) Whether to load admin code before execution.
* - 'exec_until': (mixed) Result condition for task deletion.
* - 'return': (bool) If true, captures return value.
* - 'run_js': (string) JavaScript to run after execution.
* - 'retry_limit': (int) Optional custom limit for execution attempts (overrides default).
* @param bool $is_high_priority If true, prepends the task to the beginning of the queue.
*
* @return bool|WP_Error True if the task was successfully added, false if it already exists, or WP_Error on failure.
*
* @since 8.6.4
*/
public static function add( $callback, array $task_options = array(), bool $is_high_priority = false ) {
// 1. Security Constraint: Only allow serializable callbacks (Strings or Static Methods)
// We explicitly reject Closures and Object instances to prevent serialization issues and side effects.
$is_valid_type = is_string( $callback ) || ( is_array( $callback ) && count( $callback ) === 2 && is_string( $callback[0] ) && is_string( $callback[1] ) );
if ( ! $is_valid_type ) {
return new WP_Error( 'bg_tasks_invalid_type', 'Invalid callback type. Only strings and static methods are allowed.' );
}
// 2. Validation: Ensure it is actually callable
if ( ! is_callable( $callback ) ) {
return new WP_Error( 'bg_tasks_nope', 'Specified function ' . crb_make_callable_name( $callback ) . ' is not callable or not defined.' );
}
// 3. Construct a strictly typed task structure to avoid garbage data.
// We use null coalescing to provide safe defaults (Pragmatism).
$task_details = array(
'func' => $callback,
'args' => isset( $task_options['args'] ) && is_array( $task_options['args'] ) ? $task_options['args'] : array(),
'load_admin' => ! empty( $task_options['load_admin'] ),
'exec_until' => $task_options['exec_until'] ?? null,
'return' => ! empty( $task_options['return'] ),
'run_js' => $task_options['run_js'] ?? '',
'retry_limit' => isset( $task_options['retry_limit'] ) ? (int) $task_options['retry_limit'] : null,
'retry_count' => 0, // Initialize retry counter for zombie protection
);
// Remove null values to save space, keeping logic consistent with legacy behavior
if ( is_null( $task_details['exec_until'] ) ) {
unset( $task_details['exec_until'] );
}
if ( is_null( $task_details['retry_limit'] ) ) {
unset( $task_details['retry_limit'] );
}
// 4. Ensure Determinism: Sort keys recursively to guarantee the same ID for the same data.
// We sort the details directly as the stored order does not affect logic, but reduces noise.
self::recursive_ksort( $task_details );
$task_id = sha1( serialize( $task_details ) );
// 5. Fetch current state only after preparation is done
$current_task_list = self::get_all();
if ( isset( $current_task_list[ $task_id ] ) ) {
return false;
}
// 6. Update the list efficiently
if ( $is_high_priority ) {
// Union operator (+) is faster/cleaner than array_merge for associative arrays where we want to prepend
$current_task_list = array( $task_id => $task_details ) + $current_task_list;
}
else {
$current_task_list[ $task_id ] = $task_details;
}
return cerber_update_set( self::STORAGE_KEY, $current_task_list );
}
/**
* Removes a specific background task from the queue.
*
* @param string $task_id The unique identifier of the task to delete.
*
* @return bool True if the task was found and deleted, false otherwise.
*
* @since 8.6.4
*/
public static function delete( string $task_id = '' ): bool {
if ( ! $current_task_list = self::get_all() ) {
return false;
}
if ( ! isset( $current_task_list[ $task_id ] ) ) {
return false;
}
unset( $current_task_list[ $task_id ] );
return cerber_update_set( self::STORAGE_KEY, $current_task_list );
}
/**
* Processes a single background task.
*
* Encapsulates validation, execution, error handling, and lifecycle management (retries/deletion)
* for a single unit of work.
*
* @param string $task_id The unique ID of the task.
* @param array<string, mixed> $task_details The task configuration and state.
*
* @return array<string, mixed> The execution result log entry.
*
* @since 9.6.12
*/
private static function process_single_task( string $task_id, array $task_details ): array {
$callback = crb_array_get( $task_details, 'func' );
// 1. Validation: Ensure callback is executable
if ( ! is_callable( $callback ) ) {
$error_message = 'Function ' . crb_make_callable_name( $callback ) . ' is not callable or not defined';
cerber_error_log( $error_message, 'BG TASK' );
self::delete( $task_id );
return array(
'status' => 'error',
'error' => $error_message,
);
}
// 2. Garbage Collection: Remove tasks missing required 'exec_until' logic if implicitly expected
// Note: Legacy behavior dictates deletion, but execution proceeds once.
if ( ! isset( $task_details['exec_until'] ) ) {
self::delete( $task_id );
}
// 3. Environment Setup
if ( ! empty( $task_details['load_admin'] ) ) {
cerber_load_admin_code();
}
// 4. Execution
$callback_arguments = crb_array_get( $task_details, 'args', array() );
try {
nexus_diag_log( 'Launching bg task: ' . crb_make_callable_name( $callback ) );
ob_start();
$execution_result = call_user_func_array( $callback, $callback_arguments );
$output_buffer = ob_get_clean();
// 5. Post-Execution Logic
if ( isset( $task_details['exec_until'] ) ) {
if ( $task_details['exec_until'] === $execution_result ) {
// Task completed successfully based on condition
self::delete( $task_id );
}
else {
// Logic for Zombie Tasks (Infinite Loop Protection)
$current_retries = (int) ( $task_details['retry_count'] ?? 0 ) + 1;
$max_retries = (int) ( $task_details['retry_limit'] ?? self::MAX_RETRIES );
if ( $current_retries >= $max_retries ) {
$abort_message = 'Task ' . $task_id . ' aborted: execution limit reached (' . $max_retries . ' attempts).';
cerber_error_log( $abort_message, 'BG TASK' );
self::delete( $task_id ); // Kill the zombie
return array(
'status' => 'aborted',
'error' => $abort_message,
'result' => $execution_result,
'output' => $output_buffer,
);
}
else {
// Update retry counter for the next run
self::update( $task_id, array( 'retry_count' => $current_retries ) );
}
}
}
$log_entry = array(
'status' => 'executed',
'result' => $execution_result,
'run_js' => crb_array_get( $task_details, 'run_js' ),
'output' => $output_buffer,
);
// Capture WP_Error message if present
if ( $execution_result instanceof WP_Error ) {
$log_entry['error'] = $execution_result->get_error_message();
}
return $log_entry;
} catch ( \Throwable $e ) {
// Critical Fault Isolation
if ( ob_get_level() > 0 ) {
ob_end_clean();
}
$error_message = 'Task execution failed: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine();
cerber_error_log( $error_message, 'BG TASK' );
return array(
'status' => 'error',
'error' => $error_message,
);
}
}
/**
* Updates specific fields of an existing task.
*
* Useful for persisting state changes like retry counters without re-adding the task.
*
* @param string $task_id The ID of the task to update.
* @param array<string, mixed> $changes Associative array of fields to update.
*
* @return bool True on success, false if task not found.
*
* @since 9.6.12
*/
private static function update( string $task_id, array $changes ): bool {
$task_list = self::get_all();
if ( ! isset( $task_list[ $task_id ] ) ) {
return false;
}
// Merge changes into existing task details
$task_list[ $task_id ] = array_merge( $task_list[ $task_id ], $changes );
return cerber_update_set( self::STORAGE_KEY, $task_list );
}
/**
* Helper to recursively sort array by keys for deterministic serialization.
*
* @param array $array Reference to the array to sort.
*
* @return void
*
* @since 9.6.12
*/
private static function recursive_ksort( array &$array ): void {
foreach ( $array as &$value ) {
if ( is_array( $value ) ) {
self::recursive_ksort( $value );
}
}
ksort( $array );
}
}
Home - Capital GMC Buick Regina
Skip to content
{{ $t(category) }}
Error
{{vehicle.modelData.year}} {{vehicle.modelData.make}} {{vehicle.modelData.model}}
Starting from {{vehicle.modelData.startingPrice | moneyFormat(lang)}}
Welcome to Capital GMC BUICK – REGINA
Thank you for choosing Capital GMC Buick | Regina, your premier certified Buick and GMC dealership proudly serving drivers in Regina and the surrounding communities. Whether you’re searching for a brand-new Buick or GMC vehicle or a meticulously inspected pre-owned model, we have a diverse selection to match your needs and lifestyle.
Beyond our impressive inventory, we offer a seamless and stress-free financing experience through our well-connected finance centre, where our team of experts is dedicated to securing the best loan or lease options for you, quickly, transparently, and hassle-free.
But our commitment to you doesn’t stop at the sale. Our state-of-the-art service centre is staffed with skilled Buick and GMC technicians who use the latest equipment and genuine OEM parts to keep your vehicle running at its best. From routine maintenance to complex repairs, we’ve got you covered.
Experience top-tier customer service, quality vehicles, and expert care, all in one place. Visit Capital GMC Buick | Regina today or call us at 306-205-8072 with any questions. We’re here to help!
Ask a Question
Capital GMC Buick – Regina
Contact Us
Have a question or need assistance? Fill out the form and we will reach out to you as soon as possible.
Notice: JavaScript is required for this content.
CLOSE
Schedule a Visit
Let us know when you are coming and how we can assist you. We can ensure someone will be on hand to help you out at the desired date and time.
Notice: JavaScript is required for this content.
CLOSE
Find a Career
Have a look at our list of available positions and apply online today to join our team!
×
Opportunities to Grow
The auto industry is constantly changing and we want to continue to grow. We offer growth, leadership & mentorship programs to allow our staff to grow with us.
×
Competitive Salary
We have a significant earning potential with incentive-based pay in most roles. We also offer an employee referral bonus with paid bonuses.
×
Health & Dental
We offer a comprehensive benefits package including extended health, dental, and vision care. We also include paramedical, life insurance, paid sick leave, short & long-term disability coverages.
×
Vacation
We value our employees and want everyone to take their vacation time. We offer a minimum of 2 weeks vacation each year.
×
Training & Development
We have many opportunities for paid education and training in-house as well as training from the Manufacturer.
×
$10,000 Cash Giveaway – Terms & Conditions
All October long, stop by Capital GMC Buick Cadillac, to enter for your chance to win $10,000 cash. No purchase is required, but entries must be made in-store.
The contest is open to residents of Saskatchewan who are 18+. Dealership employees and their households are not eligible. Entries will be accepted from October 1 to October 31, 2025. A random draw will take place on November 1, 2025.
The prize is one $10,000 award, paid by cheque, and must be accepted as awarded. Winner will be contacted by phone or email and must respond within 7 days or another entry may be drawn. Odds of winning depend on the number of entries received.By entering, you agree that Capital Automotive Group may use your name and photo for winner announcements. The contest is governed by the laws of Saskatchewan.
Notice: JavaScript is required for this content.
CLOSE