Skip to content

Commit d6c279b

Browse files
committed
Move tms attachments to separate bucket
1 parent fdad9a9 commit d6c279b

File tree

6 files changed

+38
-35
lines changed

6 files changed

+38
-35
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[versions]
22
# Development versions
33
commons-dev = "f7c7d2c"
4-
commons-dao-dev = "f7ac74d"
4+
commons-dao-dev = "82ec540518"
55
plugin-api-dev = "c4040dd"
66

77
# Platform versions

src/main/java/com/epam/ta/reportportal/core/tms/service/TmsAttachmentServiceImpl.java

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

33
import com.epam.reportportal.rules.exception.ErrorType;
44
import com.epam.reportportal.rules.exception.ReportPortalException;
5-
import com.epam.ta.reportportal.binary.impl.AttachmentDataStoreService;
5+
import com.epam.ta.reportportal.binary.tms.TmsAttachmentDataStoreService;
66
import com.epam.ta.reportportal.core.tms.db.entity.TmsAttachment;
77
import com.epam.ta.reportportal.core.tms.db.repository.TmsAttachmentRepository;
88
import com.epam.ta.reportportal.core.tms.db.repository.TmsManualScenarioPreconditionsAttachmentRepository;
@@ -34,7 +34,7 @@
3434
public class TmsAttachmentServiceImpl implements TmsAttachmentService {
3535

3636
private final TmsAttachmentRepository tmsAttachmentRepository;
37-
private final AttachmentDataStoreService attachmentDataStoreService;
37+
private final TmsAttachmentDataStoreService tmsAttachmentDataStoreService;
3838
private final TmsAttachmentMapper tmsAttachmentMapper;
3939
private final TmsStepAttachmentRepository tmsStepAttachmentRepository;
4040
private final TmsTextManualScenarioAttachmentRepository tmsTextManualScenarioAttachmentRepository;
@@ -51,7 +51,7 @@ public UploadAttachmentRS uploadAttachment(MultipartFile file) {
5151
}
5252

5353
try {
54-
var fileId = attachmentDataStoreService.save(file.getOriginalFilename(),
54+
var fileId = tmsAttachmentDataStoreService.save(file.getOriginalFilename(),
5555
file.getInputStream());
5656

5757
var attachment = tmsAttachmentMapper.convertToAttachment(fileId, file);
@@ -80,7 +80,7 @@ public void deleteAttachment(Long attachmentId) {
8080

8181
try {
8282
// Delete file from data store
83-
attachmentDataStoreService.delete(attachment.getPathToFile());
83+
tmsAttachmentDataStoreService.delete(attachment.getPathToFile());
8484

8585
// Delete attachment record
8686
tmsAttachmentRepository.deleteById(attachmentId);
@@ -109,7 +109,7 @@ public void cleanupExpiredAttachments() {
109109
// Delete files from data store
110110
expiredAttachments.forEach(attachment -> {
111111
try {
112-
attachmentDataStoreService.delete(attachment.getPathToFile());
112+
tmsAttachmentDataStoreService.delete(attachment.getPathToFile());
113113
} catch (Exception e) {
114114
log.warn("Failed to delete file {} for expired attachment {}: {}",
115115
attachment.getPathToFile(), attachment.getId(), e.getMessage());
@@ -144,15 +144,15 @@ public TmsAttachment duplicateTmsAttachment(TmsAttachment originalAttachment) {
144144

145145
try {
146146
// Step 1: Load original file from data store
147-
var originalFileStream = attachmentDataStoreService.load(originalAttachment.getPathToFile())
147+
var originalFileStream = tmsAttachmentDataStoreService.load(originalAttachment.getPathToFile())
148148
.orElseThrow(() -> new ReportPortalException(ErrorType.NOT_FOUND,
149149
"Original attachment file not found: " + originalAttachment.getPathToFile()));
150150

151151
// Step 2: Generate new unique filename to avoid conflicts
152152
var newFileName = generateDuplicateFileName(originalAttachment.getFileName());
153153

154154
// Step 3: Save file copy to data store
155-
var newFileId = attachmentDataStoreService.save(newFileName, originalFileStream);
155+
var newFileId = tmsAttachmentDataStoreService.save(newFileName, originalFileStream);
156156

157157
// Step 4: Create duplicated attachment entity
158158
var duplicatedAttachment = tmsAttachmentMapper.duplicateAttachment(originalAttachment,

src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,4 @@ rp.oauth2.providers.internal.algorithm=HS256
227227
rp.tms.attachment.ttl=PT24H
228228
rp.tms.attachment.cleanup.enabled=true
229229
rp.tms.attachment.cleanup.cleanup.cron=PT1H
230+
tms.datastore.type: filesystem

src/test/java/com/epam/ta/reportportal/core/tms/service/TmsAttachmentServiceImplTest.java

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.epam.reportportal.rules.exception.ErrorType;
2020
import com.epam.reportportal.rules.exception.ReportPortalException;
21-
import com.epam.ta.reportportal.binary.impl.AttachmentDataStoreService;
21+
import com.epam.ta.reportportal.binary.tms.TmsAttachmentDataStoreService;
2222
import com.epam.ta.reportportal.core.tms.db.entity.TmsAttachment;
2323
import com.epam.ta.reportportal.core.tms.db.repository.TmsAttachmentRepository;
2424
import com.epam.ta.reportportal.core.tms.db.repository.TmsManualScenarioPreconditionsAttachmentRepository;
@@ -27,7 +27,6 @@
2727
import com.epam.ta.reportportal.core.tms.dto.UploadAttachmentRS;
2828
import com.epam.ta.reportportal.core.tms.mapper.TmsAttachmentMapper;
2929
import java.io.ByteArrayInputStream;
30-
import java.io.IOException;
3130
import java.io.InputStream;
3231
import java.time.Duration;
3332
import java.time.Instant;
@@ -53,7 +52,7 @@ class TmsAttachmentServiceImplTest {
5352
private TmsAttachmentRepository tmsAttachmentRepository;
5453

5554
@Mock
56-
private AttachmentDataStoreService attachmentDataStoreService;
55+
private TmsAttachmentDataStoreService tmsAttachmentDataStoreService;
5756

5857
@Mock
5958
private TmsAttachmentMapper tmsAttachmentMapper;
@@ -106,7 +105,7 @@ void setUp() {
106105
@Test
107106
void uploadAttachment_ShouldSucceed_WhenValidFile() throws Exception {
108107
// Given valid file to upload
109-
when(attachmentDataStoreService.save(anyString(), any(InputStream.class))).thenReturn(fileId);
108+
when(tmsAttachmentDataStoreService.save(anyString(), any(InputStream.class))).thenReturn(fileId);
110109
when(tmsAttachmentMapper.convertToAttachment(fileId, file)).thenReturn(attachment);
111110
when(tmsAttachmentRepository.save(attachment)).thenReturn(attachment);
112111
when(tmsAttachmentMapper.convertToUploadAttachmentRS(attachment)).thenReturn(
@@ -120,7 +119,7 @@ void uploadAttachment_ShouldSucceed_WhenValidFile() throws Exception {
120119
assertEquals(uploadAttachmentRS.getId(), result.getId());
121120
assertEquals(uploadAttachmentRS.getFileName(), result.getFileName());
122121

123-
verify(attachmentDataStoreService).save(eq("test.txt"), any(InputStream.class));
122+
verify(tmsAttachmentDataStoreService).save(eq("test.txt"), any(InputStream.class));
124123
verify(tmsAttachmentMapper).convertToAttachment(fileId, file);
125124
verify(tmsAttachmentRepository).save(attachment);
126125
verify(tmsAttachmentMapper).convertToUploadAttachmentRS(attachment);
@@ -138,13 +137,13 @@ void uploadAttachment_ShouldThrowException_WhenFileIsEmpty() {
138137
assertEquals(ErrorType.BAD_REQUEST_ERROR, exception.getErrorType());
139138
assertEquals("Error in handled Request. Please, check specified parameters: 'File cannot be empty'", exception.getMessage());
140139

141-
verifyNoInteractions(attachmentDataStoreService, tmsAttachmentMapper, tmsAttachmentRepository);
140+
verifyNoInteractions(tmsAttachmentDataStoreService, tmsAttachmentMapper, tmsAttachmentRepository);
142141
}
143142

144143
@Test
145144
void uploadAttachment_ShouldThrowException_WhenDataStoreServiceFails() throws Exception {
146145
// Given data store service throws IOException
147-
when(attachmentDataStoreService.save(anyString(), any(InputStream.class)))
146+
when(tmsAttachmentDataStoreService.save(anyString(), any(InputStream.class)))
148147
.thenThrow(new RuntimeException("Storage error"));
149148

150149
// When/Then exception should be thrown when storage fails
@@ -154,7 +153,7 @@ void uploadAttachment_ShouldThrowException_WhenDataStoreServiceFails() throws Ex
154153
assertEquals(ErrorType.BINARY_DATA_CANNOT_BE_SAVED, exception.getErrorType());
155154
assertTrue(exception.getMessage().contains("Failed to upload attachment"));
156155

157-
verify(attachmentDataStoreService).save(eq("test.txt"), any(InputStream.class));
156+
verify(tmsAttachmentDataStoreService).save(eq("test.txt"), any(InputStream.class));
158157
verifyNoInteractions(tmsAttachmentRepository);
159158
}
160159

@@ -189,15 +188,15 @@ void getTmsAttachment_ShouldReturnEmpty_WhenNotExists() {
189188
void deleteAttachment_ShouldSucceed_WhenAttachmentExists() {
190189
// Given attachment exists in repository
191190
when(tmsAttachmentRepository.findById(attachmentId)).thenReturn(Optional.of(attachment));
192-
doNothing().when(attachmentDataStoreService).delete(fileId);
191+
doNothing().when(tmsAttachmentDataStoreService).delete(fileId);
193192
doNothing().when(tmsAttachmentRepository).deleteById(attachmentId);
194193

195194
// When deleting existing attachment
196195
sut.deleteAttachment(attachmentId);
197196

198197
// Then attachment should be deleted from both data store and repository
199198
verify(tmsAttachmentRepository).findById(attachmentId);
200-
verify(attachmentDataStoreService).delete(fileId);
199+
verify(tmsAttachmentDataStoreService).delete(fileId);
201200
verify(tmsAttachmentRepository).deleteById(attachmentId);
202201
}
203202

@@ -214,15 +213,15 @@ void deleteAttachment_ShouldThrowException_WhenAttachmentNotFound() {
214213
assertTrue(exception.getMessage().contains("Attachment not found: " + attachmentId));
215214

216215
verify(tmsAttachmentRepository).findById(attachmentId);
217-
verifyNoInteractions(attachmentDataStoreService);
216+
verifyNoInteractions(tmsAttachmentDataStoreService);
218217
verify(tmsAttachmentRepository, never()).deleteById(attachmentId);
219218
}
220219

221220
@Test
222221
void deleteAttachment_ShouldThrowException_WhenDataStoreDeleteFails() {
223222
// Given attachment exists but data store delete operation fails
224223
when(tmsAttachmentRepository.findById(attachmentId)).thenReturn(Optional.of(attachment));
225-
doThrow(new RuntimeException("Delete failed")).when(attachmentDataStoreService).delete(fileId);
224+
doThrow(new RuntimeException("Delete failed")).when(tmsAttachmentDataStoreService).delete(fileId);
226225

227226
// When/Then exception should be thrown when data store delete fails
228227
var exception = assertThrows(ReportPortalException.class,
@@ -231,7 +230,7 @@ void deleteAttachment_ShouldThrowException_WhenDataStoreDeleteFails() {
231230
assertEquals(ErrorType.UNCLASSIFIED_REPORT_PORTAL_ERROR, exception.getErrorType());
232231

233232
verify(tmsAttachmentRepository).findById(attachmentId);
234-
verify(attachmentDataStoreService).delete(fileId);
233+
verify(tmsAttachmentDataStoreService).delete(fileId);
235234
}
236235

237236
@Test
@@ -288,8 +287,8 @@ void cleanupExpiredAttachments_ShouldCleanup_WhenExpiredAttachmentsExist() {
288287

289288
// Then expired attachments should be cleaned up from both data store and repository
290289
verify(tmsAttachmentRepository).findExpiredAttachments(any(Instant.class));
291-
verify(attachmentDataStoreService).delete("path1");
292-
verify(attachmentDataStoreService).delete("path2");
290+
verify(tmsAttachmentDataStoreService).delete("path1");
291+
verify(tmsAttachmentDataStoreService).delete("path2");
293292
verify(tmsAttachmentRepository).deleteByIds(Arrays.asList(1L, 2L));
294293
}
295294

@@ -304,7 +303,7 @@ void cleanupExpiredAttachments_ShouldDoNothing_WhenNoExpiredAttachments() {
304303

305304
// Then no cleanup operations should be performed
306305
verify(tmsAttachmentRepository).findExpiredAttachments(any(Instant.class));
307-
verifyNoInteractions(attachmentDataStoreService);
306+
verifyNoInteractions(tmsAttachmentDataStoreService);
308307
verify(tmsAttachmentRepository, never()).deleteByIds(anyList());
309308
}
310309

@@ -317,15 +316,15 @@ void cleanupExpiredAttachments_ShouldContinueOnFileDeleteError() {
317316

318317
when(tmsAttachmentRepository.findExpiredAttachments(any(Instant.class)))
319318
.thenReturn(List.of(expiredAttachment));
320-
doThrow(new RuntimeException("File delete failed")).when(attachmentDataStoreService)
319+
doThrow(new RuntimeException("File delete failed")).when(tmsAttachmentDataStoreService)
321320
.delete("path1");
322321

323322
// When cleaning up expired attachments
324323
sut.cleanupExpiredAttachments();
325324

326325
// Then cleanup should continue despite file delete error
327326
verify(tmsAttachmentRepository).findExpiredAttachments(any(Instant.class));
328-
verify(attachmentDataStoreService).delete("path1");
327+
verify(tmsAttachmentDataStoreService).delete("path1");
329328
verify(tmsAttachmentRepository).deleteByIds(List.of(1L));
330329
}
331330

@@ -382,9 +381,9 @@ void duplicateTmsAttachment_ShouldSucceed_WhenValidAttachment() throws Exception
382381

383382
var originalFileStream = new ByteArrayInputStream("test content".getBytes());
384383

385-
when(attachmentDataStoreService.load(attachment.getPathToFile()))
384+
when(tmsAttachmentDataStoreService.load(attachment.getPathToFile()))
386385
.thenReturn(Optional.of(originalFileStream));
387-
when(attachmentDataStoreService.save(anyString(), any(InputStream.class))).thenReturn(
386+
when(tmsAttachmentDataStoreService.save(anyString(), any(InputStream.class))).thenReturn(
388387
newFileId);
389388
when(tmsAttachmentMapper.duplicateAttachment(eq(attachment), eq(newFileId)))
390389
.thenReturn(duplicatedAttachment);
@@ -397,34 +396,34 @@ void duplicateTmsAttachment_ShouldSucceed_WhenValidAttachment() throws Exception
397396
assertNotNull(result);
398397
assertEquals(duplicatedAttachment, result);
399398

400-
verify(attachmentDataStoreService).load(attachment.getPathToFile());
401-
verify(attachmentDataStoreService).save(anyString(), eq(originalFileStream));
399+
verify(tmsAttachmentDataStoreService).load(attachment.getPathToFile());
400+
verify(tmsAttachmentDataStoreService).save(anyString(), eq(originalFileStream));
402401
verify(tmsAttachmentMapper).duplicateAttachment(attachment, newFileId);
403402
verify(tmsAttachmentRepository).save(duplicatedAttachment);
404403
}
405404

406405
@Test
407406
void duplicateTmsAttachment_ShouldThrowException_WhenOriginalFileNotFound() {
408407
// Given original file does not exist in data store
409-
when(attachmentDataStoreService.load(attachment.getPathToFile())).thenReturn(Optional.empty());
408+
when(tmsAttachmentDataStoreService.load(attachment.getPathToFile())).thenReturn(Optional.empty());
410409

411410
// When/Then exception should be thrown when original file is not found
412411
var exception = assertThrows(ReportPortalException.class,
413412
() -> sut.duplicateTmsAttachment(attachment));
414413

415414
assertEquals(ErrorType.BINARY_DATA_CANNOT_BE_SAVED, exception.getErrorType());
416415

417-
verify(attachmentDataStoreService).load(attachment.getPathToFile());
416+
verify(tmsAttachmentDataStoreService).load(attachment.getPathToFile());
418417
verifyNoInteractions(tmsAttachmentRepository);
419418
}
420419

421420
@Test
422421
void duplicateTmsAttachment_ShouldThrowException_WhenDataStoreSaveFails() throws Exception {
423422
// Given original file exists but data store save operation fails
424423
var originalFileStream = new ByteArrayInputStream("test content".getBytes());
425-
when(attachmentDataStoreService.load(attachment.getPathToFile()))
424+
when(tmsAttachmentDataStoreService.load(attachment.getPathToFile()))
426425
.thenReturn(Optional.of(originalFileStream));
427-
when(attachmentDataStoreService.save(anyString(), any(InputStream.class)))
426+
when(tmsAttachmentDataStoreService.save(anyString(), any(InputStream.class)))
428427
.thenThrow(new RuntimeException("Storage error"));
429428

430429
// When/Then exception should be thrown when data store save fails

src/test/resources/application-unittest.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ embedded:
2323
spring:
2424
flyway:
2525
clean-disabled: false
26+
tms:
27+
datastore:
28+
type: filesystem

0 commit comments

Comments
 (0)