Skip to content

Commit

Permalink
Merge pull request #779 from 10up/fix/759
Browse files Browse the repository at this point in the history
fix/759: Add background processing for Embeddings Classification
  • Loading branch information
dkotter authored Jul 12, 2024
2 parents f76507b + cf615ac commit 0198c28
Show file tree
Hide file tree
Showing 7 changed files with 448 additions and 22 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"php": ">=7.4",
"yahnis-elsts/plugin-update-checker": "5.1",
"ua-parser/uap-php": "dev-master",
"aws/aws-sdk-php": "^3.300"
"aws/aws-sdk-php": "^3.300",
"woocommerce/action-scheduler": "3.8.1"
},
"autoload": {
"psr-4": {
Expand Down
47 changes: 45 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 133 additions & 0 deletions includes/Classifai/EmbeddingsScheduler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

namespace Classifai;

use ActionScheduler_Action;
use ActionScheduler_DBLogger;
use ActionScheduler_Store;

class EmbeddingsScheduler {

/**
* The name of the job.
*
* @var string
*/
private $job_name = '';

/**
* The name of the provider.
*
* @var string
*/
private $provider_name = '';

/**
* EmbeddingsScheduler constructor.
*
* @param string $job_name The name of the job.
* @param string $provider_name The label of the provider.
*/
public function __construct( $job_name = '', $provider_name = '' ) {
$this->job_name = $job_name;
$this->provider_name = $provider_name;
}

/**
* Initialize the class.
*/
public function init() {
add_filter( 'heartbeat_send', [ $this, 'check_embedding_generation_status' ] );
add_action( 'classifai_before_feature_nav', [ $this, 'render_embeddings_generation_status' ] );
add_action( 'action_scheduler_after_execute', [ $this, 'log_failed_embeddings' ], 10, 2 );
}

/**
* Check if embeddings generation is in progress.
*
* @return bool
*/
public function is_embeddings_generation_in_progress(): bool {
if ( ! class_exists( 'ActionScheduler_Store' ) ) {
return false;
}

$store = ActionScheduler_Store::instance();

$action_id = $store->find_action(
$this->job_name,
array(
'status' => ActionScheduler_Store::STATUS_PENDING,
)
);

return ! empty( $action_id );
}

/**
* Render the embeddings generation status notice.
*/
public function render_embeddings_generation_status() {
if ( ! $this->is_embeddings_generation_in_progress() ) {
return;
}
?>

<div class="notice notice-info classifai-classification-embeddings-message">
<p>
<?php
printf(
'<strong>%1$s</strong>: %2$s',
esc_html( $this->provider_name ),
esc_html__( 'Generation of embeddings is in progress.', 'classifai' )
)
?>
</p>
</div>

<?php
}

/**
* AJAX callback to check the status of embeddings generation.
*
* @param array $response The heartbeat response.
* @return array
*/
public function check_embedding_generation_status( $response ) {
$response['classifaiEmbedInProgress'] = $this->is_embeddings_generation_in_progress();

return $response;
}

/**
* Logs failed embeddings.
*
* @param int $action_id The action ID.
* @param ActionScheduler_Action $action The action object.
*/
public function log_failed_embeddings( $action_id, $action ) {
if ( ! class_exists( 'ActionScheduler_DBLogger' ) ) {
return;
}

if ( $this->job_name !== $action->get_hook() ) {
return;
}

$args = $action->get_args();

if ( ! isset( $args['args'] ) && ! isset( $args['args']['exclude'] ) ) {
return;
}

$excludes = $args['args']['exclude'];

if ( empty( $excludes ) || ( 1 === count( $excludes ) && in_array( 1, $excludes, true ) ) ) {
return;
}

$logger = new ActionScheduler_DBLogger();
$logger->log( $action_id, sprintf( 'Embeddings failed for terms: %s', implode( ', ', $excludes ) ) );
}
}
20 changes: 20 additions & 0 deletions includes/Classifai/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function enable() {
add_action( 'admin_init', [ $this, 'maybe_migrate_to_v3' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_assets' ] );
add_filter( 'plugin_action_links_' . CLASSIFAI_PLUGIN_BASENAME, array( $this, 'filter_plugin_action_links' ) );
add_action( 'after_classifai_init', [ $this, 'load_action_scheduler' ] );
}

/**
Expand Down Expand Up @@ -172,6 +173,7 @@ public function enqueue_admin_assets() {
get_asset_info( 'admin', 'dependencies' ),
array(
'jquery-ui-dialog',
'heartbeat',
)
),
get_asset_info( 'admin', 'version' ),
Expand Down Expand Up @@ -234,6 +236,24 @@ public function filter_plugin_action_links( $links ): array {
);
}

/**
* Load the Action Scheduler library.
*/
public function load_action_scheduler() {
$feature = new \Classifai\Features\Classification();
$is_feature_being_enabled = false;

if ( isset( $_POST['classifai_feature_classification'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
$is_feature_being_enabled = sanitize_text_field( wp_unslash( $_POST['classifai_feature_classification']['status'] ?? false ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}

if ( ! ( $feature->is_enabled() || '1' === $is_feature_being_enabled ) ) {
return;
}

require_once CLASSIFAI_PLUGIN_DIR . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
}

/**
* Migrate the existing settings to v3 if necessary.
*
Expand Down
Loading

0 comments on commit 0198c28

Please sign in to comment.