feat: Add option to delete a application snapshot (#21216)
## Description
This PR adds the option to delete an application snapshot in the
following cases:
- A DELETE API that'll delete an application snapshot
- The restore API should delete the underlying application snapshot if
the restore is successful
Fixes #21215
Media
> A video or a GIF is preferred. when using Loom, don’t embed because it
looks like it’s a GIF. instead, just link to the video
## Type of change
> Please delete options that are not relevant.
- Chore (housekeeping or task changes that don't impact user perception)
## How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Provide
instructions, so we can reproduce.
> Please also list any relevant details for your test configuration.
> Delete anything that is not important
- Manual
- JUnit tests
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or
manual QA
- [ ] Organized project review call with relevant stakeholders after
Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
This commit is contained in:
parent
dfc0983ed4
commit
ba81cb2ea1
|
|
@ -201,6 +201,14 @@ public class ApplicationControllerCE extends BaseController<ApplicationService,
|
|||
.map(applicationSnapshot -> new ResponseDTO<>(HttpStatus.OK.value(), applicationSnapshot, null));
|
||||
}
|
||||
|
||||
@DeleteMapping("/snapshot/{id}")
|
||||
public Mono<ResponseDTO<Boolean>> deleteSnapshotWithoutApplicationJson(@PathVariable String id, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
|
||||
log.debug("Going to delete snapshot with application id: {}, branch: {}", id, branchName);
|
||||
|
||||
return applicationSnapshotService.deleteSnapshot(id, branchName)
|
||||
.map(isDeleted -> new ResponseDTO<>(HttpStatus.OK.value(), isDeleted, null));
|
||||
}
|
||||
|
||||
@PostMapping("/snapshot/{id}/restore")
|
||||
public Mono<ResponseDTO<Application>> restoreSnapshot(@PathVariable String id, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
|
||||
log.debug("Going to restore snapshot with application id: {}, branch: {}", id, branchName);
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@ public interface ApplicationSnapshotServiceCE {
|
|||
Mono<ApplicationSnapshot> getWithoutDataByApplicationId(String applicationId, String branchName);
|
||||
|
||||
Mono<Application> restoreSnapshot(String applicationId, String branchName);
|
||||
|
||||
Mono<Boolean> deleteSnapshot(String applicationId, String branchName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,11 @@ public class ApplicationSnapshotServiceCEImpl implements ApplicationSnapshotServ
|
|||
return importExportApplicationService.importApplicationInWorkspace(
|
||||
application.getWorkspaceId(), applicationJson, application.getId(), branchName
|
||||
);
|
||||
});
|
||||
})
|
||||
.flatMap(application ->
|
||||
applicationSnapshotRepository.deleteAllByApplicationId(application.getId())
|
||||
.thenReturn(application)
|
||||
);
|
||||
}
|
||||
|
||||
private Mono<String> getApplicationJsonStringFromSnapShot(String applicationId) {
|
||||
|
|
@ -134,4 +138,16 @@ public class ApplicationSnapshotServiceCEImpl implements ApplicationSnapshotServ
|
|||
}
|
||||
return applicationSnapshots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> deleteSnapshot(String applicationId, String branchName) {
|
||||
// find root application by applicationId and branchName
|
||||
return applicationService.findBranchedApplicationId(branchName, applicationId, applicationPermission.getEditPermission())
|
||||
.switchIfEmpty(Mono.error(
|
||||
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, applicationId))
|
||||
)
|
||||
.flatMap(branchedAppId ->
|
||||
applicationSnapshotRepository.deleteAllByApplicationId(branchedAppId).thenReturn(Boolean.TRUE)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import reactor.test.StepVerifier;
|
|||
import reactor.util.function.Tuple2;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -210,8 +211,8 @@ public class ApplicationSnapshotServiceTest {
|
|||
pageDTO.setApplicationId(application.getId());
|
||||
return applicationPageService.createPage(pageDTO)
|
||||
.then(applicationSnapshotService.restoreSnapshot(application.getId(), null))
|
||||
.then(newPageService.findApplicationPages(application.getId(), null, null, ApplicationMode.EDIT));
|
||||
});
|
||||
.then(newPageService.findApplicationPages(application.getId(), null, null, ApplicationMode.EDIT));
|
||||
});
|
||||
|
||||
// not using Mono.zip because we want pagesBeforeSnapshot to finish first
|
||||
Mono<Tuple2<ApplicationPagesDTO, ApplicationPagesDTO>> tuple2Mono = pagesBeforeSnapshot
|
||||
|
|
@ -225,4 +226,50 @@ public class ApplicationSnapshotServiceTest {
|
|||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails("api_user")
|
||||
public void restoreSnapshot_WhenSuccessfullyRestored_SnapshotDeleted() {
|
||||
String uniqueString = UUID.randomUUID().toString();
|
||||
|
||||
// create a new workspace
|
||||
Workspace workspace = new Workspace();
|
||||
workspace.setName("Test workspace " + uniqueString);
|
||||
|
||||
Flux<ApplicationSnapshot> snapshotFlux = workspaceService.create(workspace)
|
||||
.flatMap(createdWorkspace -> {
|
||||
Application testApplication = new Application();
|
||||
testApplication.setName("App before snapshot");
|
||||
return applicationPageService.createApplication(testApplication, workspace.getId());
|
||||
}).flatMap(application -> { // create a snapshot
|
||||
return applicationSnapshotService.createApplicationSnapshot(application.getId(), null)
|
||||
.thenReturn(application);
|
||||
})
|
||||
.flatMapMany(application ->
|
||||
applicationSnapshotService.restoreSnapshot(application.getId(), null)
|
||||
.thenMany(applicationSnapshotRepository.findByApplicationId(application.getId()))
|
||||
);
|
||||
|
||||
StepVerifier.create(snapshotFlux)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteSnapshot_WhenSnapshotExists_Deleted() {
|
||||
String testAppId = "app-" + UUID.randomUUID().toString();
|
||||
ApplicationSnapshot snapshot1 = new ApplicationSnapshot();
|
||||
snapshot1.setChunkOrder(1);
|
||||
snapshot1.setApplicationId(testAppId);
|
||||
|
||||
ApplicationSnapshot snapshot2 = new ApplicationSnapshot();
|
||||
snapshot2.setApplicationId(testAppId);
|
||||
snapshot2.setChunkOrder(2);
|
||||
|
||||
Flux<ApplicationSnapshot> snapshotFlux = applicationSnapshotRepository.saveAll(List.of(snapshot1, snapshot2))
|
||||
.then(applicationSnapshotService.deleteSnapshot(testAppId, null))
|
||||
.thenMany(applicationSnapshotRepository.findByApplicationId(testAppId));
|
||||
|
||||
StepVerifier.create(snapshotFlux)
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +134,9 @@ public class ApplicationSnapshotServiceUnitTest {
|
|||
Mockito.when(importExportApplicationService.importApplicationInWorkspace(eq(application.getWorkspaceId()), argThat(matchApplicationJson), eq(branchedAppId), eq(branch)))
|
||||
.thenReturn(Mono.just(application));
|
||||
|
||||
Mockito.when(applicationSnapshotRepository.deleteAllByApplicationId(branchedAppId))
|
||||
.thenReturn(Mono.just("application").then());
|
||||
|
||||
StepVerifier.create(applicationSnapshotService.restoreSnapshot(defaultAppId, branch))
|
||||
.assertNext(application1 -> {
|
||||
assertThat(application1.getName()).isEqualTo(application.getName());
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user