Skip to content

Commit c18b2d7

Browse files
committed
Cleanup data older than 10 minutes
1 parent c165f0a commit c18b2d7

File tree

12 files changed

+218
-10
lines changed

12 files changed

+218
-10
lines changed

service/docker/cleanup.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
cd /var/www/html
4+
php bin/console app:purge-old-data
5+
6+
echo "$(date): Executed data purge"

service/docker/start.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ until php -r "try { new PDO('pgsql:host=database;dbname=${POSTGRES_DB:-app}', '$
1212
done
1313
echo ""
1414

15-
# Run migrations
1615
echo "Running database migrations..."
1716
php bin/console doctrine:migrations:migrate --no-interaction || true
1817

19-
# Start services
2018
echo "Starting services..."
2119
service nginx start
22-
php-fpm
20+
php-fpm &
21+
22+
while true; do
23+
echo "Cleanup Database..."
24+
php bin/console app:purge-old-data || echo "Purge error"
25+
sleep 60
26+
done
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Adds created_at timestamp to entities that need it
12+
*/
13+
final class Version20250520135054 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return 'Add created_at timestamp to all tables that need it';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// Add timestamps to problems table
23+
$this->addSql('ALTER TABLE problems ADD created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
24+
25+
// Add timestamps to private_problems table
26+
$this->addSql('ALTER TABLE private_problems ADD created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
27+
28+
// Add timestamps to private_access table
29+
$this->addSql('ALTER TABLE private_access ADD created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
30+
31+
// Add timestamps to users table
32+
$this->addSql('ALTER TABLE users ADD created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP');
33+
}
34+
35+
public function down(Schema $schema): void
36+
{
37+
// Remove timestamps from problems table
38+
$this->addSql('ALTER TABLE problems DROP COLUMN created_at');
39+
40+
// Remove timestamps from private_problems table
41+
$this->addSql('ALTER TABLE private_problems DROP COLUMN created_at');
42+
43+
// Remove timestamps from private_access table
44+
$this->addSql('ALTER TABLE private_access DROP COLUMN created_at');
45+
46+
// Remove timestamps from users table
47+
$this->addSql('ALTER TABLE users DROP COLUMN created_at');
48+
}
49+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace App\Command;
4+
5+
use Doctrine\DBAL\Connection;
6+
use Symfony\Component\Console\Attribute\AsCommand;
7+
use Symfony\Component\Console\Command\Command;
8+
use Symfony\Component\Console\Input\InputInterface;
9+
use Symfony\Component\Console\Output\OutputInterface;
10+
use Symfony\Component\Console\Style\SymfonyStyle;
11+
12+
#[AsCommand(
13+
name: 'app:purge-old-data',
14+
description: 'Purges all data older than 10 minutes from the database',
15+
)]
16+
class PurgeOldDataCommand extends Command
17+
{
18+
private Connection $connection;
19+
20+
public function __construct(Connection $connection)
21+
{
22+
parent::__construct();
23+
$this->connection = $connection;
24+
}
25+
26+
protected function execute(InputInterface $input, OutputInterface $output): int
27+
{
28+
$io = new SymfonyStyle($input, $output);
29+
$io->title('Purging data older than 10 minutes');
30+
31+
$timestamp = new \DateTime('-10 minutes');
32+
$formattedTimestamp = $timestamp->format('Y-m-d H:i:s');
33+
34+
$tables = [
35+
'problems',
36+
'private_problems',
37+
'private_access',
38+
'users',
39+
'feedback'
40+
];
41+
42+
$totalDeleted = 0;
43+
44+
foreach ($tables as $table) {
45+
$timestampColumn = 'created_at';
46+
47+
if ($table === 'feedback') {
48+
$timestampColumn = 'created_at';
49+
}
50+
51+
$sql = "DELETE FROM $table WHERE $timestampColumn < :timestamp";
52+
53+
try {
54+
$stmt = $this->connection->prepare($sql);
55+
$stmt->bindValue('timestamp', $formattedTimestamp);
56+
$result = $stmt->executeStatement();
57+
$totalDeleted += $result;
58+
59+
$io->text(sprintf('Deleted %d rows from %s', $result, $table));
60+
} catch (\Exception $e) {
61+
$io->error(sprintf('Error deleting from %s: %s', $table, $e->getMessage()));
62+
}
63+
}
64+
65+
$io->success(sprintf('Successfully purged %d rows older than 10 minutes', $totalDeleted));
66+
67+
return Command::SUCCESS;
68+
}
69+
}

service/src/Controller/FeedbackController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace App\Controller;
44

5-
use App\Command\ImageHandler;
65
use App\Entity\Feedback;
76
use App\Entity\User;
7+
use App\Service\ImageHandler;
88
use Doctrine\ORM\EntityManagerInterface;
99
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
1010
use Symfony\Component\HttpFoundation\Request;

service/src/Controller/ProblemController.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
namespace App\Controller;
44

5-
use App\Command\CodeExecutor;
65
use App\DatabaseManager\FindProblemsByAuthorId;
6+
use App\Entity\PrivateAccess;
7+
use App\Entity\PrivateProblem;
78
use App\Entity\Problem;
89
use App\Entity\User;
9-
use App\Entity\PrivateProblem;
10-
use App\Entity\PrivateAccess;
10+
use App\Service\CodeExecutor;
1111
use Doctrine\ORM\EntityManagerInterface;
1212
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
13+
use Symfony\Component\HttpFoundation\JsonResponse;
1314
use Symfony\Component\HttpFoundation\Request;
1415
use Symfony\Component\HttpFoundation\Response;
15-
use Symfony\Component\HttpFoundation\JsonResponse;
1616
use Symfony\Component\Routing\Annotation\Route;
1717

1818
class ProblemController extends AbstractController

service/src/Entity/PrivateAccess.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ class PrivateAccess
2121
#[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
2222
private ?User $user = null;
2323

24+
#[ORM\Column(type: 'datetime')]
25+
private \DateTimeInterface $createdAt;
26+
27+
public function __construct()
28+
{
29+
$this->createdAt = new \DateTime();
30+
}
31+
2432
public function getId(): ?int
2533
{
2634
return $this->id;
@@ -49,4 +57,16 @@ public function setUser(?User $user): self
4957

5058
return $this;
5159
}
60+
61+
public function getCreatedAt(): \DateTimeInterface
62+
{
63+
return $this->createdAt;
64+
}
65+
66+
public function setCreatedAt(\DateTimeInterface $createdAt): self
67+
{
68+
$this->createdAt = $createdAt;
69+
70+
return $this;
71+
}
5272
}

service/src/Entity/PrivateProblem.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ class PrivateProblem
3535
#[ORM\JoinColumn(name: 'author_id', referencedColumnName: 'id', nullable: true)]
3636
private ?User $author = null;
3737

38+
#[ORM\Column(type: 'datetime')]
39+
private \DateTimeInterface $createdAt;
40+
41+
public function __construct()
42+
{
43+
$this->createdAt = new \DateTime();
44+
}
45+
3846
public function getId(): ?int
3947
{
4048
return $this->id;
@@ -123,4 +131,16 @@ public function setAuthor(?User $author): self
123131

124132
return $this;
125133
}
134+
135+
public function getCreatedAt(): \DateTimeInterface
136+
{
137+
return $this->createdAt;
138+
}
139+
140+
public function setCreatedAt(\DateTimeInterface $createdAt): self
141+
{
142+
$this->createdAt = $createdAt;
143+
144+
return $this;
145+
}
126146
}

service/src/Entity/Problem.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ class Problem
3838
#[ORM\JoinColumn(name: 'author_id', referencedColumnName: 'id', nullable: true)]
3939
private ?User $author = null;
4040

41+
#[ORM\Column(type: 'datetime')]
42+
private \DateTimeInterface $createdAt;
43+
44+
public function __construct()
45+
{
46+
$this->createdAt = new \DateTime();
47+
}
48+
4149
public function getId(): ?int
4250
{
4351
return $this->id;
@@ -138,4 +146,16 @@ public function setAuthor(?User $author): self
138146

139147
return $this;
140148
}
149+
150+
public function getCreatedAt(): \DateTimeInterface
151+
{
152+
return $this->createdAt;
153+
}
154+
155+
public function setCreatedAt(\DateTimeInterface $createdAt): self
156+
{
157+
$this->createdAt = $createdAt;
158+
159+
return $this;
160+
}
141161
}

service/src/Entity/User.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
2424
#[ORM\Column(type: 'boolean')]
2525
private bool $isAdmin = false;
2626

27+
#[ORM\Column(type: 'datetime')]
28+
private \DateTimeInterface $createdAt;
29+
30+
public function __construct()
31+
{
32+
$this->createdAt = new \DateTime();
33+
}
34+
2735
public function getId(): ?int
2836
{
2937
return $this->id;
@@ -84,4 +92,16 @@ public function getRoles(): array
8492
public function eraseCredentials(): void
8593
{
8694
}
95+
96+
public function getCreatedAt(): \DateTimeInterface
97+
{
98+
return $this->createdAt;
99+
}
100+
101+
public function setCreatedAt(\DateTimeInterface $createdAt): self
102+
{
103+
$this->createdAt = $createdAt;
104+
105+
return $this;
106+
}
87107
}

0 commit comments

Comments
 (0)