You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
7.1 KiB
211 lines
7.1 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Jobs;
|
|
|
|
use Exception;
|
|
use Throwable;
|
|
use App\Services\Shared\Configuration\Configuration;
|
|
use App\Services\Shared\Import\Routine\RoutineManager;
|
|
use App\Services\Shared\Import\Status\SubmissionStatus;
|
|
use App\Services\Shared\Import\Status\SubmissionStatusManager;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class ProcessImportSubmissionJob implements ShouldQueue
|
|
{
|
|
use Dispatchable;
|
|
use InteractsWithQueue;
|
|
use Queueable;
|
|
use SerializesModels;
|
|
|
|
/**
|
|
* The number of times the job may be attempted.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $tries = 1;
|
|
|
|
/**
|
|
* The maximum number of seconds the job can run for.
|
|
*
|
|
* @var int
|
|
*/
|
|
public $timeout = 1800;
|
|
|
|
/**
|
|
* Create a new job instance.
|
|
*/
|
|
public function __construct(private string $identifier, private Configuration $configuration, private array $transactions, private string $accessToken, private string $baseUrl, private ?string $vanityUrl)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Execute the job.
|
|
*/
|
|
public function handle(): void
|
|
{
|
|
Log::info('ProcessImportSubmissionJob started', [
|
|
'identifier' => $this->identifier,
|
|
'transaction_count' => count($this->transactions),
|
|
]);
|
|
|
|
// Validate authentication credentials before proceeding
|
|
if ('' === $this->accessToken) {
|
|
throw new Exception('Access token is empty - cannot authenticate with Firefly III');
|
|
}
|
|
|
|
if ('' === $this->baseUrl) {
|
|
throw new Exception('Base URL is empty - cannot connect to Firefly III');
|
|
}
|
|
|
|
Log::info('Job authentication credentials validation', [
|
|
'identifier' => $this->identifier,
|
|
'access_token_length' => strlen($this->accessToken),
|
|
'access_token_preview' => substr($this->accessToken, 0, 20).'...',
|
|
'base_url' => $this->baseUrl,
|
|
'vanity_url' => $this->vanityUrl ?? 'null',
|
|
]);
|
|
|
|
// Backup original configuration
|
|
$originalConfig = [
|
|
'importer.access_token' => config('importer.access_token'),
|
|
'importer.url' => config('importer.url'),
|
|
'importer.vanity_url' => config('importer.vanity_url'),
|
|
];
|
|
|
|
Log::debug('Original config backup', [
|
|
'identifier' => $this->identifier,
|
|
'original_token_length' => strlen(
|
|
(string) $originalConfig['importer.access_token']
|
|
),
|
|
'original_url' => $originalConfig['importer.url'],
|
|
'original_vanity' => $originalConfig['importer.vanity_url'],
|
|
]);
|
|
|
|
try {
|
|
// Set authentication context for this job
|
|
config([
|
|
'importer.access_token' => $this->accessToken,
|
|
'importer.url' => $this->baseUrl,
|
|
'importer.vanity_url' => $this->vanityUrl ?? $this->baseUrl,
|
|
]);
|
|
|
|
Log::debug('Authentication context set for job', [
|
|
'identifier' => $this->identifier,
|
|
'base_url' => $this->baseUrl,
|
|
'vanity_url' => $this->vanityUrl ?? $this->baseUrl,
|
|
'access_token_length' => strlen($this->accessToken),
|
|
]);
|
|
|
|
// Verify config was actually set
|
|
$verifyToken = config('importer.access_token');
|
|
$verifyUrl = config('importer.url');
|
|
|
|
Log::debug('Config verification after setting', [
|
|
'identifier' => $this->identifier,
|
|
'config_token_matches' => $verifyToken === $this->accessToken,
|
|
'config_url_matches' => $verifyUrl === $this->baseUrl,
|
|
'config_token_length' => strlen((string) $verifyToken),
|
|
'config_url' => $verifyUrl,
|
|
]);
|
|
|
|
if ($verifyToken !== $this->accessToken) {
|
|
throw new Exception(
|
|
'Failed to set access token in config properly'
|
|
);
|
|
}
|
|
|
|
if ($verifyUrl !== $this->baseUrl) {
|
|
throw new Exception(
|
|
'Failed to set base URL in config properly'
|
|
);
|
|
}
|
|
|
|
// Set initial running status
|
|
SubmissionStatusManager::setSubmissionStatus(
|
|
SubmissionStatus::SUBMISSION_RUNNING,
|
|
$this->identifier
|
|
);
|
|
|
|
// Initialize routine manager and execute import
|
|
$routine = new RoutineManager($this->identifier);
|
|
$routine->setConfiguration($this->configuration);
|
|
$routine->setTransactions($this->transactions);
|
|
|
|
Log::debug('Starting routine execution', [
|
|
'identifier' => $this->identifier,
|
|
]);
|
|
|
|
// Execute the import process
|
|
$routine->start();
|
|
|
|
// Set completion status
|
|
SubmissionStatusManager::setSubmissionStatus(
|
|
SubmissionStatus::SUBMISSION_DONE,
|
|
$this->identifier
|
|
);
|
|
|
|
Log::info('ProcessImportSubmissionJob completed successfully', [
|
|
'identifier' => $this->identifier,
|
|
'messages' => count($routine->getAllMessages()),
|
|
'warnings' => count($routine->getAllWarnings()),
|
|
'errors' => count($routine->getAllErrors()),
|
|
]);
|
|
} catch (Throwable $e) {
|
|
Log::error('ProcessImportSubmissionJob failed', [
|
|
'identifier' => $this->identifier,
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
// Set error status
|
|
SubmissionStatusManager::setSubmissionStatus(
|
|
SubmissionStatus::SUBMISSION_ERRORED,
|
|
$this->identifier
|
|
);
|
|
|
|
// Re-throw to mark job as failed
|
|
throw $e;
|
|
} finally {
|
|
// Always restore original configuration
|
|
config($originalConfig);
|
|
|
|
Log::debug('Authentication context restored', [
|
|
'identifier' => $this->identifier,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle a job failure.
|
|
*/
|
|
public function failed(Throwable $exception): void
|
|
{
|
|
Log::error('ProcessImportSubmissionJob marked as failed', [
|
|
'identifier' => $this->identifier,
|
|
'exception' => $exception->getMessage(),
|
|
]);
|
|
|
|
// Ensure error status is set even if job fails catastrophically
|
|
SubmissionStatusManager::setSubmissionStatus(
|
|
SubmissionStatus::SUBMISSION_ERRORED,
|
|
$this->identifier
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the tags that should be assigned to the job.
|
|
*
|
|
* @return array<int, string>
|
|
*/
|
|
public function tags(): array
|
|
{
|
|
return ['import-submission', $this->identifier];
|
|
}
|
|
}
|