Jake Vanderwerf
2026-08-26 ccf5e61a075c35d24befc175994b5cb8957ca322
inc/managers/queue/executors/IntegrationExecutor.php
@@ -3,6 +3,9 @@
use JVBase\managers\queue\{Executor, Operation, Progress, Result};
use Exception;
use JVBase\integrations\Integrations;
use JVBase\integrations\ServiceMap;
use JVBase\managers\Errors;
if (!defined('ABSPATH')) {
   exit;
@@ -18,7 +21,7 @@
 *          {integration}_sync_from, {integration}_sync_customer, etc.
 *
 * Registration (in Integrations::registerAdditionalHooks):
 *   $queue = JVB()->queue();
 *   $queue = Queue::getInstance();
 *   $queue->registry()->register('helcim_sync_to', new TypeConfig(
 *       executor: new IntegrationExecutor(),
 *       chunkKey: 'items',
@@ -28,11 +31,8 @@
 */
final class IntegrationExecutor implements Executor
{
   /**
    * Map of integration service names to class identifiers.
    * Populated on first use from JVB()->connect().
    */
   private array $integrationCache = [];
   use ServiceMap;
   public function execute(Operation $operation, Progress $progress): Result
   {
@@ -60,7 +60,7 @@
         };
      } catch (Exception $e) {
         JVB()->error()->log(
         Errors::getInstance()->log(
            '[IntegrationExecutor]:execute',
            $e->getMessage(),
            [
@@ -86,9 +86,6 @@
    */
   private function parseOperationType(string $type): array
   {
      // Remove BASE prefix if present (e.g. 'jvb_helcim_sync_to' → 'helcim_sync_to')
      $type = str_replace(BASE, '', $type);
      $pos = strpos($type, '_');
      if ($pos === false) {
         throw new Exception("Invalid integration operation type: {$type}");
@@ -103,21 +100,12 @@
   /**
    * Resolve integration instance, optionally for a specific user
    */
   private function resolveIntegration(string $serviceName, int $userId): ?object
   private function resolveIntegration(string $serviceName, ?int $userId = null): ?object
   {
      if (!isset($this->integrationCache[$serviceName])) {
         $this->integrationCache[$serviceName] = JVB()->connect($serviceName);
      if ($userId === 0) {
         $userId = null;
      }
      $integration = $this->integrationCache[$serviceName];
      // If operation has a user context, re-instantiate for that user
      if ($integration && $userId) {
         $class = get_class($integration);
         return new $class($userId);
      }
      return $integration;
      return $this->getServiceUser($serviceName, $userId);
   }
   /*****************************************************************
@@ -137,6 +125,11 @@
         return new Result(outcome: 'success', result: ['synced' => [], 'message' => 'No items to sync']);
      }
      if ($integration->hasBatchUpdate()) {
         $result = $integration->updateBatchToService($data['items']);
         return new Result(outcome: $result['outcome'], result: $result['result']);
      }
      foreach ($items as $postID) {
         try {
            $result = $integration->syncPostToService((int)$postID);