123 lines
3.8 KiB
PHP
123 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Temporal\UserMigration;
|
|
|
|
use Carbon\CarbonInterval;
|
|
use Temporal\Activity\ActivityOptions;
|
|
use Temporal\Common\RetryOptions;
|
|
use Temporal\Workflow;
|
|
|
|
class UserMigrationWorkflow implements UserMigrationWorkflowInterface
|
|
{
|
|
private string $status = 'pending';
|
|
private int $totalUsers = 0;
|
|
private int $batchSize = 0;
|
|
private int $processedUsers = 0;
|
|
private int $failedUsers = 0;
|
|
private bool $isPaused = false;
|
|
private int $currentBatch = 0;
|
|
private int $totalBatches = 0;
|
|
private int $retryCount = 0;
|
|
private int $rateLimitHits = 0;
|
|
|
|
/** @var UserMigrationActivityInterface */
|
|
private $activityStub;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->activityStub = Workflow::newActivityStub(
|
|
UserMigrationActivityInterface::class,
|
|
ActivityOptions::new()
|
|
->withStartToCloseTimeout(CarbonInterval::minutes(10))
|
|
->withHeartbeatTimeout(CarbonInterval::seconds(60))
|
|
->withRetryOptions(
|
|
RetryOptions::new()
|
|
->withMaximumAttempts(3)
|
|
)
|
|
);
|
|
}
|
|
|
|
public function migrate(int $totalUsers, int $batchSize, array $simulationConfig = []): \Generator
|
|
{
|
|
$this->totalUsers = $totalUsers;
|
|
$this->batchSize = $batchSize;
|
|
$this->totalBatches = (int) ceil($totalUsers / $batchSize);
|
|
|
|
try {
|
|
$this->status = 'fetching_users';
|
|
$users = yield $this->activityStub->fetchExternalUsers($totalUsers, $simulationConfig);
|
|
|
|
$this->status = 'processing';
|
|
|
|
for ($i = 0; $i < $this->totalBatches; $i++) {
|
|
if ($this->isPaused) {
|
|
$this->status = 'paused';
|
|
yield Workflow::await(fn () => !$this->isPaused);
|
|
$this->status = 'processing';
|
|
}
|
|
|
|
$this->currentBatch = $i + 1;
|
|
|
|
$batchUsers = array_slice($users, $i * $this->batchSize, $this->batchSize);
|
|
|
|
$validUsers = yield $this->activityStub->validateUsers($batchUsers, $simulationConfig);
|
|
|
|
$result = yield $this->activityStub->createAccounts($validUsers, $simulationConfig);
|
|
|
|
$this->processedUsers += $result['created'];
|
|
$this->failedUsers += $result['failed'];
|
|
|
|
$attempt = $result['attempt'] ?? 1;
|
|
if ($attempt > 1) {
|
|
$this->retryCount += ($attempt - 1);
|
|
}
|
|
|
|
yield $this->activityStub->sendWelcomeEmails($result['created_ids'], $simulationConfig);
|
|
}
|
|
|
|
$this->status = 'generating_report';
|
|
$report = yield $this->activityStub->generateMigrationReport(
|
|
$this->totalUsers,
|
|
$this->processedUsers,
|
|
$this->failedUsers,
|
|
$simulationConfig
|
|
);
|
|
} catch (\Throwable $e) {
|
|
$this->status = 'failed';
|
|
throw $e;
|
|
}
|
|
|
|
$this->status = 'completed';
|
|
|
|
return $report;
|
|
}
|
|
|
|
public function pause(): void
|
|
{
|
|
$this->isPaused = true;
|
|
}
|
|
|
|
public function resume(): void
|
|
{
|
|
$this->isPaused = false;
|
|
}
|
|
|
|
public function getProgress(): array
|
|
{
|
|
return [
|
|
'status' => $this->status,
|
|
'totalUsers' => $this->totalUsers,
|
|
'processedUsers' => $this->processedUsers,
|
|
'failedUsers' => $this->failedUsers,
|
|
'isPaused' => $this->isPaused,
|
|
'currentBatch' => $this->currentBatch,
|
|
'totalBatches' => $this->totalBatches,
|
|
'percentComplete' => $this->totalUsers > 0
|
|
? round(($this->processedUsers / $this->totalUsers) * 100, 2)
|
|
: 0.0,
|
|
'retryCount' => $this->retryCount,
|
|
'rateLimitHits' => $this->rateLimitHits,
|
|
];
|
|
}
|
|
}
|