Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apigee_edge.module
Original file line number Diff line number Diff line change
Expand Up @@ -1365,6 +1365,7 @@ function apigee_edge_user_presave(UserInterface $account) {
}
$developer = $result->getDeveloper();
$developer->save();
\Drupal::getContainer()->get('apigee_edge.dev_sync.last_update_tracker')->set($developer->getEmail(), \Drupal::time()->getCurrentTime());
}
catch (\Exception $exception) {
$previous = $exception->getPrevious();
Expand All @@ -1386,6 +1387,7 @@ function apigee_edge_user_presave(UserInterface $account) {
// "originalEmail" property's value on the entity.
$developer->enforceIsNew(TRUE);
$developer->save();
\Drupal::getContainer()->get('apigee_edge.dev_sync.last_update_tracker')->set($developer->getEmail(), \Drupal::time()->getCurrentTime());
}
catch (\Exception $exception) {
$context = [
Expand All @@ -1410,6 +1412,7 @@ function apigee_edge_user_presave(UserInterface $account) {
$developer->enforceIsNew(FALSE);
try {
$developer->save();
\Drupal::getContainer()->get('apigee_edge.dev_sync.last_update_tracker')->set($result->getDeveloper()->getEmail(), \Drupal::time()->getCurrentTime());
}
catch (ApiException $exception) {
$logger->error("Unable to update existing @developer developer's data after registered on the portal.", $context);
Expand Down
5 changes: 5 additions & 0 deletions apigee_edge.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,8 @@ services:
apigee_edge.post_user_delete_action_performer:
class: Drupal\apigee_edge\User\RemoveRelatedDeveloperAccountSynchronousPostUserDeleteActionPerformer
arguments: ['@entity_type.manager', '@logger.channel.apigee_edge']

apigee_edge.dev_sync.last_update_tracker:
class: Drupal\Core\KeyValueStore\KeyValueStoreInterface
factory: [ '@keyvalue', 'get' ]
arguments: [ 'apigee_edge.dev_sync.last_update_tracker' ]
5 changes: 5 additions & 0 deletions src/Job/DeveloperCreateUpdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ protected function executeRequest() {
if ($result->getSuccessfullyAppliedChanges() > 0) {
$result->getDeveloper()->save();
}
// Record the sync attempt timestamp for the developer's email,
// regardless of whether an entity update occurred, to prevent redundant
// sync operations. This ensures that the developer will only be re-synced
// if a new relevant change is detected after this timestamp.
\Drupal::getContainer()->get('apigee_edge.dev_sync.last_update_tracker')->set($result->getDeveloper()->getEmail(), \Drupal::time()->getCurrentTime());
}
catch (\Exception $exception) {
$message = '@operation: Skipping %mail developer. @message %function (line %line of %file). <pre>@backtrace_string</pre>';
Expand Down
70 changes: 57 additions & 13 deletions src/Job/DeveloperSync.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
namespace Drupal\apigee_edge\Job;

use Drupal\apigee_edge\Entity\Developer;
use Drupal\apigee_edge\Entity\DeveloperInterface;
use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;

/**
* A job that synchronizes Apigee Edge developers and Drupal users.
Expand Down Expand Up @@ -58,6 +61,11 @@ class DeveloperSync extends EdgeJob {
*/
protected $filter = NULL;

/**
* KV store tracks last update attempts for each user/developer.
*/
protected KeyValueStoreInterface $lastUpdateTracker;

/**
* DeveloperSync constructor.
*
Expand All @@ -67,6 +75,7 @@ class DeveloperSync extends EdgeJob {
public function __construct(?string $filter) {
parent::__construct();
$this->filter = $filter;
$this->lastUpdateTracker = \Drupal::service('apigee_edge.dev_sync.last_update_tracker');
}

/**
Expand Down Expand Up @@ -130,6 +139,30 @@ protected function executeRequest() {
$this->edgeDevelopers = $this->loadDevelopers();
}

/**
* Schedules the update of a user.
*
* @param \Drupal\user\UserInterface $user
* The user.
*/
protected function scheduleUserUpdate(UserInterface $user): void {
$update_user_job = new UserUpdate($user->getEmail());
$update_user_job->setTag($this->getTag());
$this->scheduleJob($update_user_job);
}

/**
* Schedules the update of a developer.
*
* @param \Drupal\apigee_edge\Entity\DeveloperInterface $developer
* The developer.
*/
protected function scheduleDeveloper(DeveloperInterface $developer): void {
$update_developer_job = new DeveloperUpdate($developer->getEmail());
$update_developer_job->setTag($this->getTag());
$this->scheduleJob($update_developer_job);
}

/**
* {@inheritdoc}
*/
Expand All @@ -144,20 +177,31 @@ public function execute(): bool {
/** @var \Drupal\user\UserInterface $user */
$user = $this->drupalUsers[$clean_email];

$last_modified_delta = $developer->getLastModifiedAt()->getTimestamp() - $user->getChangedTime();
// Update Drupal user because the Apigee Edge developer is the most
// recent.
if ($last_modified_delta >= 0) {
$update_user_job = new UserUpdate($user->getEmail());
$update_user_job->setTag($this->getTag());
$this->scheduleJob($update_user_job);
$last_synced = $this->lastUpdateTracker->get($developer->getEmail(), 0);

if ($last_synced === 0) {
$last_modified_delta = $developer->getLastModifiedAt()->getTimestamp() - $user->getChangedTime();
if ($last_modified_delta === 0) {
$this->lastUpdateTracker->set($developer->getEmail(), \Drupal::time()->getCurrentTime());
continue;
}

// Update Drupal user because the Apigee Edge developer is the most
// recent.
if ($last_modified_delta > 0) {
$this->scheduleUserUpdate($user);
}
// Update Apigee Edge developer because the Drupal user is the most
// recent.
else {
$this->scheduleDeveloper($developer);
}
}
elseif ($last_synced < $developer->getLastModifiedAt()->getTimestamp()) {
$this->scheduleUserUpdate($user);
}
// Update Apigee Edge developer because the Drupal user is the most
// recent.
elseif ($last_modified_delta < 0) {
$update_developer_job = new DeveloperUpdate($developer->getEmail());
$update_developer_job->setTag($this->getTag());
$this->scheduleJob($update_developer_job);
elseif ($last_synced < $user->getChangedTime()) {
$this->scheduleDeveloper($developer);
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/Job/UserCreateUpdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ protected function executeRequest() {
_apigee_edge_set_sync_in_progress(TRUE);
$result->getUser()->save();
}

// Record the sync attempt timestamp for the developer's email,
// regardless of whether an entity update occurred, to prevent redundant
// sync operations. This ensures that the developer will only be re-synced
// if a new relevant change is detected after this timestamp.
\Drupal::getContainer()->get('apigee_edge.dev_sync.last_update_tracker')->set($developer->getEmail(), \Drupal::time()->getCurrentTime());
}
catch (\Exception $exception) {
$message = '@operation: Skipping %mail user. @message %function (line %line of %file). <pre>@backtrace_string</pre>';
Expand All @@ -85,8 +91,8 @@ protected function executeRequest() {
'@operation' => get_class($this),
];
$context += Error::decodeException($exception);
// Unset backtrace, exception, severity_level as they are not shown in the log message
// and throws php warning in logs.
// Unset backtrace, exception, severity_level as they are not shown in
// the log message and throws php warning in logs.
unset($context['backtrace'], $context['exception'], $context['severity_level']);

$this->logger()->error($message, $context);
Expand Down