Skip to content

Commit b5f1110

Browse files
ISSUE #1530: Allow to restrict import on activity ids
1 parent 9211e84 commit b5f1110

20 files changed

+147
-47
lines changed

src/Application/Import/ImportActivities/ImportActivities.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,30 @@
22

33
namespace App\Application\Import\ImportActivities;
44

5+
use App\Domain\Activity\ActivityIds;
56
use App\Infrastructure\CQRS\Command\DomainCommand;
67
use Symfony\Component\Console\Output\OutputInterface;
78

89
final readonly class ImportActivities extends DomainCommand
910
{
1011
public function __construct(
1112
private OutputInterface $output,
13+
private ?ActivityIds $restrictToActivityIds,
1214
) {
1315
}
1416

1517
public function getOutput(): OutputInterface
1618
{
1719
return $this->output;
1820
}
21+
22+
public function getRestrictToActivityIds(): ActivityIds
23+
{
24+
return $this->restrictToActivityIds ?? ActivityIds::empty();
25+
}
26+
27+
public function isFullImport(): bool
28+
{
29+
return $this->getRestrictToActivityIds()->isEmpty();
30+
}
1931
}

src/Application/Import/ImportActivities/ImportActivitiesCommandHandler.php

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,34 @@ public function handle(Command $command): void
5353
$allActivityIds->map(fn (ActivityId $activityId): string => (string) $activityId),
5454
$allActivityIds->toArray(),
5555
);
56-
$stravaActivities = $this->strava->getActivities();
57-
$countTotalStravaActivities = count($stravaActivities);
5856

59-
$command->getOutput()->writeln(
60-
sprintf('Status: %d out of %d activities imported', count($allActivityIds), $countTotalStravaActivities)
61-
);
57+
try {
58+
if ($command->isFullImport()) {
59+
// No restriction on activity ids, we need to execute a full import.
60+
$stravaActivities = $this->strava->getActivities();
61+
} else {
62+
// Restriction on activity ids, we want to execute a partial import.
63+
$stravaActivities = array_map(
64+
$this->strava->getActivity(...),
65+
$command->getRestrictToActivityIds()->toArray()
66+
);
67+
}
68+
} catch (StravaRateLimitHasBeenReached $exception) {
69+
$command->getOutput()->writeln(sprintf('<error>%s</error>', $exception->getMessage()));
70+
71+
return;
72+
} catch (ClientException|RequestException $exception) {
73+
$command->getOutput()->writeln(sprintf('<error>Strava API threw error: %s</error>', $exception->getMessage()));
74+
75+
return;
76+
}
77+
78+
$countTotalStravaActivitiesToImport = count($stravaActivities);
79+
if ($command->isFullImport()) {
80+
$command->getOutput()->writeln(
81+
sprintf('Status: %d out of %d activities imported', count($allActivityIds), $countTotalStravaActivitiesToImport)
82+
);
83+
}
6284

6385
$delta = 1;
6486
foreach ($stravaActivities as $rawStravaData) {
@@ -94,10 +116,11 @@ public function handle(Command $command): void
94116
}
95117

96118
try {
97-
$isNewActivity = false;
98-
if (!$this->activityWithRawDataRepository->exists($activityId)) {
119+
$isNewActivity = !$this->activityWithRawDataRepository->exists($activityId);
120+
if ($isNewActivity && $command->isFullImport()) {
121+
// When a partial import is triggered we fetch the activity from Strava beforehand.
122+
// We only need to fetch activity details when running a full import.
99123
$rawStravaData = $this->strava->getActivity($activityId);
100-
$isNewActivity = true;
101124
}
102125

103126
$context = ActivityImportContext::create(
@@ -130,7 +153,7 @@ public function handle(Command $command): void
130153
$command->getOutput()->writeln(sprintf(
131154
' => [%d/%d] Imported activity: "%s - %s"',
132155
$delta,
133-
$countTotalStravaActivities,
156+
$countTotalStravaActivitiesToImport,
134157
$activity->getName(),
135158
$activity->getStartDate()->format('d-m-Y'))
136159
);
@@ -151,7 +174,7 @@ public function handle(Command $command): void
151174
$command->getOutput()->writeln(sprintf(
152175
' => [%d/%d] %s activity: "%s - %s"',
153176
$delta,
154-
$countTotalStravaActivities,
177+
$countTotalStravaActivitiesToImport,
155178
$context->isNewActivity() ? 'Imported' : 'Updated',
156179
$activity->getName(),
157180
$activity->getStartDate()->format('d-m-Y'))
@@ -166,20 +189,23 @@ public function handle(Command $command): void
166189
return;
167190
}
168191

169-
if (count($activityIdsToDelete) === count($allActivityIds) && array_values($activityIdsToDelete) == $allActivityIds->toArray()) {
170-
throw new \RuntimeException('All activities appear to be marked for deletion. This seems like a configuration issue. Aborting to prevent data loss');
171-
}
192+
if ($command->isFullImport()) {
193+
if (count($activityIdsToDelete) === count($allActivityIds) && array_values($activityIdsToDelete) == $allActivityIds->toArray()) {
194+
throw new \RuntimeException('All activities appear to be marked for deletion. This seems like a configuration issue. Aborting to prevent data loss');
195+
}
172196

173-
foreach ($activityIdsToDelete as $activityId) {
174-
$activity = $this->activityRepository->find($activityId);
175-
$activity->delete();
176-
$this->activityRepository->delete($activity);
197+
// Only delete activities during full imports to avoid accidental deletion of data.
198+
foreach ($activityIdsToDelete as $activityId) {
199+
$activity = $this->activityRepository->find($activityId);
200+
$activity->delete();
201+
$this->activityRepository->delete($activity);
177202

178-
$command->getOutput()->writeln(sprintf(
179-
' => Deleted activity "%s - %s"',
180-
$activity->getName(),
181-
$activity->getStartDate()->format('d-m-Y'))
182-
);
203+
$command->getOutput()->writeln(sprintf(
204+
' => Deleted activity "%s - %s"',
205+
$activity->getName(),
206+
$activity->getStartDate()->format('d-m-Y'))
207+
);
208+
}
183209
}
184210
}
185211
}

src/Application/Import/ImportGear/GearImportStatus.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function __construct(
1717

1818
public function isComplete(): bool
1919
{
20-
$gearIdsOnActivities = $this->activityRepository->findUniqueGearIds();
20+
$gearIdsOnActivities = $this->activityRepository->findUniqueGearIds(null);
2121
$importedGears = $this->importedGearRepository->findAll();
2222

2323
foreach ($gearIdsOnActivities as $gearId) {

src/Application/Import/ImportGear/ImportGear.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,30 @@
22

33
namespace App\Application\Import\ImportGear;
44

5+
use App\Domain\Activity\ActivityIds;
56
use App\Infrastructure\CQRS\Command\DomainCommand;
67
use Symfony\Component\Console\Output\OutputInterface;
78

89
final readonly class ImportGear extends DomainCommand
910
{
1011
public function __construct(
1112
private OutputInterface $output,
13+
private ?ActivityIds $restrictToActivityIds,
1214
) {
1315
}
1416

1517
public function getOutput(): OutputInterface
1618
{
1719
return $this->output;
1820
}
21+
22+
public function getRestrictToActivityIds(): ActivityIds
23+
{
24+
return $this->restrictToActivityIds ?? ActivityIds::empty();
25+
}
26+
27+
public function isPartialImport(): bool
28+
{
29+
return !$this->getRestrictToActivityIds()->isEmpty();
30+
}
1931
}

src/Application/Import/ImportGear/ImportGearCommandHandler.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ public function handle(Command $command): void
3838

3939
$this->strava->setConsoleOutput($command->getOutput());
4040

41-
$stravaGearIds = $this->activityRepository->findUniqueGearIds();
41+
$allStravaGearIdsReferencedOnActivities = $this->activityRepository->findUniqueGearIds(null);
4242

4343
if ($this->customGearConfig->isFeatureEnabled()) {
4444
/** @var GearId $customGearId */
4545
foreach ($this->customGearConfig->getGearIds() as $customGearId) {
46-
if (!$stravaGearIds->has($customGearId)) {
46+
if (!$allStravaGearIdsReferencedOnActivities->has($customGearId)) {
4747
continue;
4848
}
4949

@@ -56,7 +56,13 @@ public function handle(Command $command): void
5656
}
5757
}
5858

59-
foreach ($stravaGearIds as $gearId) {
59+
$stravaGearIdsToImport = $allStravaGearIdsReferencedOnActivities;
60+
if ($command->isPartialImport()) {
61+
// We only want to update gears that are referenced on the activities to be imported.
62+
$stravaGearIdsToImport = $this->activityRepository->findUniqueGearIds($command->getRestrictToActivityIds());
63+
}
64+
65+
foreach ($stravaGearIdsToImport as $gearId) {
6066
try {
6167
$stravaGear = $this->strava->getGear($gearId);
6268
} catch (StravaRateLimitHasBeenReached $exception) {

src/Application/RunImport/RunImport.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,25 @@
44

55
namespace App\Application\RunImport;
66

7+
use App\Domain\Activity\ActivityIds;
78
use App\Infrastructure\CQRS\Command\DomainCommand;
89
use Symfony\Component\Console\Style\SymfonyStyle;
910

1011
final readonly class RunImport extends DomainCommand
1112
{
1213
public function __construct(
1314
private SymfonyStyle $output,
15+
private ?ActivityIds $restrictToActivityIds,
1416
) {
1517
}
1618

1719
public function getOutput(): SymfonyStyle
1820
{
1921
return $this->output;
2022
}
23+
24+
public function getRestrictToActivityIds(): ?ActivityIds
25+
{
26+
return $this->restrictToActivityIds;
27+
}
2128
}

src/Application/RunImport/RunImportCommandHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public function handle(Command $command): void
5151
}
5252

5353
$this->commandBus->dispatch(new ImportAthlete($output));
54-
$this->commandBus->dispatch(new ImportActivities($output));
55-
$this->commandBus->dispatch(new ImportGear($output));
54+
$this->commandBus->dispatch(new ImportActivities($output, $command->getRestrictToActivityIds()));
55+
$this->commandBus->dispatch(new ImportGear($output, $command->getRestrictToActivityIds()));
5656
$this->commandBus->dispatch(new LinkCustomGearToActivities($output));
5757
$this->commandBus->dispatch(new ImportActivitySplits($output));
5858
$this->commandBus->dispatch(new ImportActivityLaps($output));

src/Application/importDataAndBuildAppCronAction.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function run(SymfonyStyle $output): void
5656

5757
$this->commandBus->dispatch(new RunImport(
5858
output: $output,
59+
restrictToActivityIds: null,
5960
));
6061
$this->commandBus->dispatch(new RunBuild(
6162
output: $output,

src/Console/ImportStravaDataConsoleCommand.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace App\Console;
44

55
use App\Application\RunImport\RunImport;
6+
use App\Domain\Activity\ActivityId;
7+
use App\Domain\Activity\ActivityIds;
68
use App\Infrastructure\Console\ProvideConsoleIntro;
79
use App\Infrastructure\CQRS\Command\Bus\CommandBus;
810
use App\Infrastructure\Daemon\Mutex\LockName;
@@ -15,6 +17,7 @@
1517
use Psr\Log\LoggerInterface;
1618
use Symfony\Component\Console\Attribute\AsCommand;
1719
use Symfony\Component\Console\Command\Command;
20+
use Symfony\Component\Console\Input\InputArgument;
1821
use Symfony\Component\Console\Input\InputInterface;
1922
use Symfony\Component\Console\Output\OutputInterface;
2023
use Symfony\Component\Console\Style\SymfonyStyle;
@@ -36,17 +39,28 @@ public function __construct(
3639
parent::__construct();
3740
}
3841

42+
protected function configure(): void
43+
{
44+
$this->addArgument('restrictToActivityId', InputArgument::OPTIONAL);
45+
}
46+
3947
protected function execute(InputInterface $input, OutputInterface $output): int
4048
{
4149
$output = new SymfonyStyle($input, new LoggableConsoleOutput($output, $this->logger));
4250
$this->resourceUsage->startTimer();
4351
$this->outputConsoleIntro($output);
4452

53+
$restrictToActivityIds = null;
54+
if ($restrictToActivityId = $input->getArgument('restrictToActivityId')) {
55+
$restrictToActivityIds = ActivityIds::fromArray([ActivityId::fromUnprefixed($restrictToActivityId)]);
56+
}
57+
4558
$this->migrationRunner->run($output);
4659
$this->mutex->acquireLock('ImportStravaDataConsoleCommand');
4760

4861
$this->commandBus->dispatch(new RunImport(
4962
output: $output,
63+
restrictToActivityIds: $restrictToActivityIds,
5064
));
5165

5266
$this->resourceUsage->stopTimer();

src/Domain/Activity/ActivityIds.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
use App\Infrastructure\ValueObject\Collection;
88

9+
/**
10+
* @extends Collection<ActivityId>
11+
*/
912
final class ActivityIds extends Collection
1013
{
1114
public function getItemClassName(): string

0 commit comments

Comments
 (0)