Skip to content

Commit 38ba208

Browse files
Merge pull request #13 from opensoft/move-exceptions
Track move exceptions with a new table
2 parents ba5ef1e + 095a776 commit 38ba208

7 files changed

+281
-36
lines changed

Command/MoveStorageFileCommand.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Opensoft\StorageBundle\Entity\Storage;
66
use Opensoft\StorageBundle\Entity\StorageFile;
7+
use Opensoft\StorageBundle\Entity\StorageMoveException;
78
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
89
use Symfony\Component\Console\Input\InputArgument;
910
use Symfony\Component\Console\Input\InputInterface;
@@ -63,6 +64,8 @@ public function execute(InputInterface $input, OutputInterface $output)
6364
return -1;
6465
}
6566

67+
$fromStorage = $storageFile->getStorage();
68+
6669
$em = $doctrine->getManager();
6770
$em->getConnection()->beginTransaction();
6871

@@ -91,15 +94,18 @@ public function execute(InputInterface $input, OutputInterface $output)
9194

9295
$em->persist($storageFile);
9396
$em->flush();
94-
$em->clear();
9597
$em->getConnection()->commit();
9698

9799
$output->writeln(sprintf("Done moving file %d", $storageFile->getId()));
98100
} catch (\Exception $e) {
99-
$em->clear();
100101
$em->getConnection()->rollBack();
101102
$logger->critical($e);
102103

104+
// This usually happens in the $storageManager->moveStorageFile function, but we've suspended transactions, execute it here.
105+
$moveException = new StorageMoveException($storageFile, $fromStorage, $destinationStorage, $e);
106+
$em->persist($moveException);
107+
$em->flush();
108+
103109
return -1;
104110
}
105111
}

Command/PolicyExecuteCommand.php

+6
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
use Doctrine\ORM\AbstractQuery;
66
use Doctrine\ORM\EntityManager;
7+
use Doctrine\ORM\Query\Expr\Join;
78
use Opensoft\StorageBundle\Entity\Storage;
89
use Opensoft\StorageBundle\Entity\StorageFile;
910
use Opensoft\Onp\Bundle\CoreBundle\Task\Type\CommandTask;
11+
use Opensoft\StorageBundle\Entity\StorageMoveException;
1012
use Opensoft\StorageBundle\Entity\StoragePolicy;
1113
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
1214
use Symfony\Component\Console\Input\ArrayInput;
@@ -103,12 +105,16 @@ private function queueMoves($type, $moveInterval, Storage $fromStorage, Storage
103105

104106
$qb = $em->createQueryBuilder()
105107
->select('s')
108+
->distinct()
106109
->from(StorageFile::class, 's')
110+
->leftJoin('s.moveExceptions', 'm', Join::WITH, 'm.fromStorage = :fromStorageId AND m.toStorage = :toStorageId')
107111
->andWhere('s.storage = :fromStorageId')
108112
->andWhere('s.type = :fileType')
109113
->andWhere('s.createdAt < :olderThan')
114+
->andWhere('m.id IS NULL')
110115
->setParameters([
111116
'fromStorageId' => $fromStorage->getId(),
117+
'toStorageId' => $toStorage->getId(),
112118
'fileType' => $type,
113119
'olderThan' => new \DateTime($moveInterval . ' ago')
114120
])
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
* This file is part of ONP.
4+
*
5+
* Copyright (c) Opensoft (http://opensoftdev.com)
6+
*
7+
* The unauthorized use of this code outside the boundaries of
8+
* Opensoft is prohibited.
9+
*/
10+
11+
namespace Opensoft\StorageBundle\Entity\Repository;
12+
13+
use Doctrine\ORM\EntityRepository;
14+
15+
/**
16+
* @author Richard Fullmer <[email protected]>
17+
*/
18+
class StorageMoveExceptionRepository extends EntityRepository
19+
{
20+
21+
}

Entity/StorageFile.php

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Opensoft\StorageBundle\Entity;
44

5+
use Doctrine\Common\Collections\ArrayCollection;
56
use Doctrine\ORM\Mapping as ORM;
67
use Gaufrette\File as GaufretteFile;
78
use Gaufrette\Filesystem;
@@ -80,6 +81,14 @@ class StorageFile extends GaufretteFile
8081
*/
8182
private $contentHash;
8283

84+
/**
85+
* @var StorageMoveException[]
86+
*
87+
* @ORM\OneToMany(targetEntity="Opensoft\StorageBundle\Entity\StorageMoveException", mappedBy="storageFile")
88+
* @ORM\OrderBy({"createdAt" = "DESC"})
89+
*/
90+
private $moveExceptions;
91+
8392
/**
8493
* Constructor
8594
*
@@ -92,6 +101,7 @@ public function __construct($key, Filesystem $filesystem, Storage $storage)
92101
parent::__construct($key, $filesystem);
93102
$this->storage = $storage;
94103
$this->createdAt = new \DateTime();
104+
$this->moveExceptions = new ArrayCollection();
95105
}
96106

97107
/**
@@ -261,6 +271,14 @@ public function setType($type)
261271
$this->type = $type;
262272
}
263273

274+
/**
275+
* @return ArrayCollection|StorageMoveException[]
276+
*/
277+
public function getMoveExceptions()
278+
{
279+
return $this->moveExceptions;
280+
}
281+
264282
/**
265283
* @param int $precision
266284
* @return string

Entity/StorageMoveException.php

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
/**
3+
* This file is part of ONP.
4+
*
5+
* Copyright (c) Opensoft (http://opensoftdev.com)
6+
*
7+
* The unauthorized use of this code outside the boundaries of
8+
* Opensoft is prohibited.
9+
*/
10+
11+
namespace Opensoft\StorageBundle\Entity;
12+
13+
use Doctrine\ORM\Mapping as ORM;
14+
15+
/**
16+
* @author Richard Fullmer <[email protected]>
17+
*
18+
* @ORM\Entity(repositoryClass="Opensoft\StorageBundle\Entity\Repository\StorageMoveExceptionRepository")
19+
* @ORM\Table(name="storage_move_exception")
20+
*/
21+
class StorageMoveException
22+
{
23+
/**
24+
* @var int
25+
*
26+
* @ORM\Id
27+
* @ORM\Column(type="integer")
28+
* @ORM\GeneratedValue(strategy="AUTO")
29+
*/
30+
private $id;
31+
32+
/**
33+
* @var StorageFile
34+
*
35+
* @ORM\ManyToOne(targetEntity="Opensoft\StorageBundle\Entity\StorageFile", inversedBy="moveExceptions")
36+
* @ORM\JoinColumn(name="storage_file_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
37+
*/
38+
private $storageFile;
39+
40+
/**
41+
* @var Storage
42+
*
43+
* @ORM\ManyToOne(targetEntity="Opensoft\StorageBundle\Entity\Storage")
44+
* @ORM\JoinColumn(name="from_storage_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
45+
*/
46+
private $fromStorage;
47+
48+
/**
49+
* @var Storage
50+
*
51+
* @ORM\ManyToOne(targetEntity="Opensoft\StorageBundle\Entity\Storage")
52+
* @ORM\JoinColumn(name="to_storage_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
53+
*/
54+
private $toStorage;
55+
56+
/**
57+
* @var \DateTime
58+
*
59+
* @ORM\Column(type="datetime", name="created_at")
60+
*/
61+
private $createdAt;
62+
63+
/**
64+
* @var string
65+
*
66+
* @ORM\Column(type="string", name="exception_string")
67+
*/
68+
private $exceptionString;
69+
70+
/**
71+
* @var string
72+
*
73+
* @ORM\Column(type="text", name="exception_backtrace")
74+
*/
75+
private $exceptionBacktrace;
76+
77+
/**
78+
* @param StorageFile $file
79+
* @param Storage $fromStorage
80+
* @param Storage $toStorage
81+
* @param \Exception $e
82+
*/
83+
public function __construct(StorageFile $file, Storage $fromStorage, Storage $toStorage, \Exception $e)
84+
{
85+
$this->storageFile = $file;
86+
$this->fromStorage = $fromStorage;
87+
$this->toStorage = $toStorage;
88+
$this->createdAt = new \DateTime();
89+
$this->exceptionString = $e->getMessage();
90+
$this->exceptionBacktrace = $e->getTraceAsString();
91+
}
92+
93+
/**
94+
* @return int
95+
*/
96+
public function getId()
97+
{
98+
return $this->id;
99+
}
100+
101+
/**
102+
* @return StorageFile
103+
*/
104+
public function getStorageFile()
105+
{
106+
return $this->storageFile;
107+
}
108+
109+
/**
110+
* @return Storage
111+
*/
112+
public function getFromStorage()
113+
{
114+
return $this->fromStorage;
115+
}
116+
117+
/**
118+
* @return Storage
119+
*/
120+
public function getToStorage()
121+
{
122+
return $this->toStorage;
123+
}
124+
125+
/**
126+
* @return \DateTime
127+
*/
128+
public function getCreatedAt()
129+
{
130+
return $this->createdAt;
131+
}
132+
133+
/**
134+
* @return string
135+
*/
136+
public function getExceptionString()
137+
{
138+
return $this->exceptionString;
139+
}
140+
141+
/**
142+
* @return string
143+
*/
144+
public function getExceptionBacktrace()
145+
{
146+
return $this->exceptionBacktrace;
147+
}
148+
}

Resources/views/storage/show_file.html.twig

+34
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,40 @@
175175
</div>
176176
</div>
177177
</div>
178+
179+
{% if file.moveExceptions %}
180+
<div class="row">
181+
<div class="col-lg-12">
182+
<div class="ibox">
183+
<div class="ibox-title">
184+
<h5>Move Exceptions <i class="fa fa-warning"></i></h5>
185+
</div>
186+
<div class="ibox-content">
187+
<div class="table-responsive">
188+
<table class="table table-hover">
189+
<thead>
190+
<tr>
191+
<th>Timestamp</th>
192+
<th>From Storage</th>
193+
<th>To Storage</th>
194+
<th>Exception</th>
195+
</tr>
196+
</thead>
197+
{% for moveException in file.moveExceptions %}
198+
<tr>
199+
<td>{{ moveException.createdAt|date }}</td>
200+
<td>{{ moveException.fromStorage.name }}</td>
201+
<td>{{ moveException.toStorage.name }}</td>
202+
<td><p title="{{ moveException.exceptionBacktrace }}">{{ moveException.exceptionString }}</p></td>
203+
</tr>
204+
{% endfor %}
205+
</table>
206+
</div>
207+
</div>
208+
</div>
209+
</div>
210+
</div>
211+
{% endif %}
178212
{% endblock %}
179213

180214
{% block opensoft_storage_foot_script %}

0 commit comments

Comments
 (0)