Skip to content

Commit 9d59d83

Browse files
committed
#278 - Add SOFT_DELETE document event
1 parent f647fa4 commit 9d59d83

File tree

6 files changed

+80
-52
lines changed

6 files changed

+80
-52
lines changed

document-events/src/main/java/com/formkiq/module/events/document/DocumentEventType.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public interface DocumentEventType {
3535
String UPDATE = "update";
3636
/** Delete Event Type. */
3737
String DELETE = "delete";
38+
/** Soft Delete Event Type. */
39+
String SOFT_DELETE = "softDelete";
3840
/** Actions Event Type. */
3941
String ACTIONS = "actions";
4042
}

lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdRequestHandler.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import static com.formkiq.aws.dynamodb.objects.Strings.isEmpty;
3030
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_NOT_FOUND;
3131
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
32+
import static com.formkiq.module.events.document.DocumentEventType.SOFT_DELETE;
33+
3234
import java.util.ArrayList;
3335
import java.util.Collection;
3436
import java.util.List;
@@ -61,6 +63,8 @@
6163
import com.formkiq.module.actions.Action;
6264
import com.formkiq.module.actions.services.ActionsNotificationService;
6365
import com.formkiq.module.actions.services.ActionsService;
66+
import com.formkiq.module.events.EventService;
67+
import com.formkiq.module.events.document.DocumentEvent;
6468
import com.formkiq.module.lambdaservices.AwsServiceCache;
6569
import com.formkiq.stacks.api.transformers.AddDocumentRequestToDocumentItem;
6670
import com.formkiq.stacks.api.transformers.AddDocumentRequestToPresignedUrls;
@@ -130,6 +134,10 @@ public ApiRequestHandlerResponse delete(final LambdaLogger logger,
130134
throw new NotFoundException("Document " + documentId + " not found.");
131135
}
132136

137+
if (softDelete) {
138+
publishSoftDelete(awsservice, authorization, siteId, documentId);
139+
}
140+
133141
ApiResponse resp = new ApiMessageResponse("'" + documentId + "' object deleted");
134142
return new ApiRequestHandlerResponse(SC_OK, resp);
135143

@@ -143,6 +151,14 @@ public ApiRequestHandlerResponse delete(final LambdaLogger logger,
143151
}
144152
}
145153

154+
private void publishSoftDelete(final AwsServiceCache awsservice,
155+
final ApiAuthorization authorization, final String siteId, final String documentId) {
156+
EventService es = awsservice.getExtension(EventService.class);
157+
DocumentEvent de = new DocumentEvent().siteId(siteId).documentId(documentId).type(SOFT_DELETE)
158+
.userId(authorization.getUsername());
159+
es.publish(de);
160+
}
161+
146162
@Override
147163
public ApiRequestHandlerResponse get(final LambdaLogger logger,
148164
final ApiGatewayRequestEvent event, final ApiAuthorization authorization,

lambda-api/src/test/java/com/formkiq/stacks/api/handler/AbstractApiClientRequestTest.java

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
2727
import static com.formkiq.aws.services.lambda.ApiAuthorizationBuilder.COGNITO_READ_SUFFIX;
2828

29+
import java.util.ArrayList;
2930
import java.util.Collection;
3031
import java.util.List;
3132
import java.util.Map;
@@ -137,6 +138,8 @@ public abstract class AbstractApiClientRequestTest {
137138
protected MappingsApi mappingsApi = new MappingsApi(this.client);
138139
/** {@link UserManagementApi}. */
139140
protected UserManagementApi userManagementApi = new UserManagementApi(this.client);
141+
/** Sqs Messages. */
142+
private final List<Map<String, Object>> sqsMessages = new ArrayList<>();
140143

141144
/**
142145
* Convert JSON to Object.
@@ -152,11 +155,15 @@ protected <T> T fromJson(final String json, final Class<T> clazz) {
152155

153156
/**
154157
* Get Sqs Messages.
155-
*
156-
* @return {@link List} {@link Message}
158+
*
159+
* @param eventType {@link String}
160+
* @param documentId {@link String}
161+
*
162+
* @return {@link Map} {@link Message}
157163
* @throws InterruptedException InterruptedException
158164
*/
159-
public List<Message> getSqsMessages() throws InterruptedException {
165+
public Map<String, Object> getSqsMessages(final String eventType, final String documentId)
166+
throws InterruptedException {
160167

161168
String sqsDocumentEventUrl = localstack.getSqsDocumentEventUrl();
162169

@@ -165,24 +172,38 @@ public List<Message> getSqsMessages() throws InterruptedException {
165172
SqsService sqsService = awsServices.getExtension(SqsService.class);
166173

167174
List<Message> msgs = sqsService.receiveMessages(sqsDocumentEventUrl).messages();
168-
while (msgs.isEmpty()) {
175+
List<Map<String, Object>> list = msgs.stream().map(this::transform).toList();
176+
sqsMessages.addAll(list);
177+
178+
while (sqsMessages.isEmpty() || !isMatch(sqsMessages, eventType, documentId)) {
169179
Thread.sleep(SLEEP);
170180
msgs = sqsService.receiveMessages(sqsDocumentEventUrl).messages();
181+
sqsMessages.addAll(msgs.stream().map(this::transform).toList());
171182
}
172183

173-
for (Message msg : msgs) {
174-
sqsService.deleteMessage(sqsDocumentEventUrl, msg.receiptHandle());
175-
}
184+
return sqsMessages.stream().filter(m -> isMatch(m, eventType, documentId)).findAny().get();
185+
}
186+
187+
private boolean isMatch(final List<Map<String, Object>> msgs, final String eventType,
188+
final String documentId) {
189+
return msgs.stream().anyMatch(m -> isMatch(m, eventType, documentId));
190+
}
176191

177-
return msgs;
192+
private static boolean isMatch(final Map<String, Object> m, final String eventType,
193+
final String documentId) {
194+
return eventType.equals(m.get("type")) && documentId.equals(m.get("documentId"));
195+
}
196+
197+
private Map<String, Object> transform(final Message msg) {
198+
Map<String, Object> map = fromJson(msg.body(), Map.class);
199+
return fromJson((String) map.get("Message"), Map.class);
178200
}
179201

180202
/**
181203
* Clear Sqs Messages.
182204
*
183-
* @throws InterruptedException InterruptedException
184205
*/
185-
public void clearSqsMessages() throws InterruptedException {
206+
public void clearSqsMessages() {
186207

187208
String sqsDocumentEventUrl = localstack.getSqsDocumentEventUrl();
188209

@@ -202,7 +223,6 @@ public void clearSqsMessages() throws InterruptedException {
202223
* @param e {@link ApiException}
203224
* @return {@link ValidationException}
204225
*/
205-
@SuppressWarnings("unchecked")
206226
public Collection<Map<String, Object>> getValidationErrors(final ApiException e) {
207227
Gson gson = new GsonBuilder().create();
208228

lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsActionsRequestTest.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import com.formkiq.aws.dynamodb.DynamoDbService;
5454
import com.formkiq.aws.dynamodb.DynamoDbServiceExtension;
5555
import com.formkiq.aws.dynamodb.model.DocumentItem;
56-
import com.formkiq.aws.services.lambda.GsonUtil;
5756
import com.formkiq.client.invoker.ApiException;
5857
import com.formkiq.client.model.AddAction;
5958
import com.formkiq.client.model.AddActionParameters;
@@ -81,11 +80,13 @@
8180
import com.formkiq.stacks.dynamodb.DocumentVersionService;
8281
import com.formkiq.stacks.dynamodb.DocumentVersionServiceExtension;
8382
import com.formkiq.validation.ValidationException;
84-
import software.amazon.awssdk.services.sqs.model.Message;
83+
import org.junit.jupiter.api.Timeout;
8584

8685
/** Unit Tests for request /documents/{documentId}/actions. */
8786
public class DocumentsActionsRequestTest extends AbstractApiClientRequestTest {
8887

88+
/** Timeout. */
89+
private static final long TIMEOUT = 10;
8990
/** {@link ConfigService}. */
9091
private ConfigService configService;
9192
/** {@link DocumentService}. */
@@ -165,8 +166,8 @@ public void testHandleGetDocumentActions01() throws Exception {
165166
*
166167
* @throws Exception an error has occurred
167168
*/
168-
@SuppressWarnings("unchecked")
169169
@Test
170+
@Timeout(TIMEOUT)
170171
public void testHandlePostDocumentActions01() throws Exception {
171172

172173
for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
@@ -208,16 +209,10 @@ public void testHandlePostDocumentActions01() throws Exception {
208209
assertEquals(ActionStatus.PENDING, actions.get(i).status());
209210
assertEquals("{url=https://localhost}", actions.get(i).parameters().toString());
210211

211-
List<Message> sqsMessages = getSqsMessages();
212-
assertEquals(1, sqsMessages.size());
213-
214-
Map<String, String> map =
215-
GsonUtil.getInstance().fromJson(sqsMessages.get(0).body(), Map.class);
216-
217-
map = GsonUtil.getInstance().fromJson(map.get("Message"), Map.class);
218-
assertNotNull(map.get("siteId"));
219-
assertEquals(documentId, map.get("documentId"));
220-
assertEquals("actions", map.get("type"));
212+
Map<String, Object> sqsMessage = getSqsMessages("actions", documentId);
213+
assertNotNull(sqsMessage.get("siteId"));
214+
assertEquals(documentId, sqsMessage.get("documentId"));
215+
assertEquals("actions", sqsMessage.get("type"));
221216
}
222217
}
223218

lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsIdRequestTest.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import java.util.UUID;
3434

3535
import com.formkiq.aws.services.lambda.ApiResponseStatus;
36-
import com.formkiq.aws.services.lambda.GsonUtil;
3736
import com.formkiq.client.model.AddAttribute;
3837
import com.formkiq.client.model.AddAttributeRequest;
3938
import com.formkiq.client.model.AddDocumentAttribute;
@@ -62,18 +61,17 @@
6261
import com.formkiq.client.model.SetDocumentRestoreResponse;
6362
import com.formkiq.testutils.aws.DynamoDbExtension;
6463
import com.formkiq.testutils.aws.LocalStackExtension;
65-
import software.amazon.awssdk.services.sqs.model.Message;
6664

6765
/** Unit Tests for request /documents/{documentId}. */
6866
@ExtendWith(DynamoDbExtension.class)
6967
@ExtendWith(LocalStackExtension.class)
7068
public class DocumentsIdRequestTest extends AbstractApiClientRequestTest {
7169

7270
/** Test Timeout. */
73-
private static final int TEST_TIMEOUT = 30;
71+
private static final int TEST_TIMEOUT = 10;
7472

7573
@BeforeEach
76-
void beforeEach() throws InterruptedException {
74+
void beforeEach() {
7775
clearSqsMessages();
7876
}
7977

@@ -223,6 +221,7 @@ private List<Document> getSoftDeletedDocuments(final String siteId) throws ApiEx
223221
* @throws Exception an error has occurred
224222
*/
225223
@Test
224+
@Timeout(TEST_TIMEOUT)
226225
public void testHandleSetDocumentRestore01() throws Exception {
227226

228227
for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
@@ -256,9 +255,19 @@ public void testHandleSetDocumentRestore01() throws Exception {
256255
documents = getDocuments(siteId);
257256
assertEquals(1, documents.size());
258257
assertEquals("test.txt", documents.get(0).getPath());
258+
expectSoftDeleteSqsMessage(siteId, documentId);
259259
}
260260
}
261261

262+
private void expectSoftDeleteSqsMessage(final String siteId, final String documentId)
263+
throws InterruptedException {
264+
Map<String, Object> message = getSqsMessages("softDelete", documentId);
265+
assertEquals("softDelete", message.get("type"));
266+
assertEquals(siteId != null ? siteId : "default", message.get("siteId"));
267+
assertEquals(documentId, message.get("documentId"));
268+
assertEquals("joesmith", message.get("userId"));
269+
}
270+
262271
/**
263272
* PUT /documents/{documentId}/restore request, document not found.
264273
*
@@ -757,15 +766,9 @@ public void testUpdate08() throws Exception {
757766
this.documentsApi.updateDocument(documentId, updateReq, siteId, null);
758767

759768
// then
760-
List<Message> sqsMessages = getSqsMessages();
761-
assertEquals(1, sqsMessages.size());
762-
763-
Map<String, String> map =
764-
GsonUtil.getInstance().fromJson(sqsMessages.get(0).body(), Map.class);
765-
766-
map = GsonUtil.getInstance().fromJson(map.get("Message"), Map.class);
767-
assertEquals(documentId, map.get("documentId"));
768-
assertEquals("actions", map.get("type"));
769+
Map<String, Object> message = getSqsMessages("actions", documentId);
770+
assertEquals(documentId, message.get("documentId"));
771+
assertEquals("actions", message.get("type"));
769772
}
770773
}
771774

lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsRequestTest.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import com.formkiq.aws.s3.S3Service;
3131
import com.formkiq.aws.s3.S3ServiceExtension;
3232
import com.formkiq.aws.services.lambda.ApiResponseStatus;
33-
import com.formkiq.aws.services.lambda.GsonUtil;
3433
import com.formkiq.client.invoker.ApiException;
3534
import com.formkiq.client.invoker.ApiResponse;
3635
import com.formkiq.client.model.AddAction;
@@ -66,7 +65,6 @@
6665
import org.junit.jupiter.api.Test;
6766
import org.junit.jupiter.api.Timeout;
6867
import org.junit.jupiter.api.extension.ExtendWith;
69-
import software.amazon.awssdk.services.sqs.model.Message;
7068

7169
import java.util.Arrays;
7270
import java.util.List;
@@ -91,7 +89,7 @@ public class DocumentsRequestTest extends AbstractApiClientRequestTest {
9189
private static final int TEST_TIMEOUT = 10;
9290

9391
@BeforeEach
94-
void beforeEach() throws InterruptedException {
92+
void beforeEach() {
9593
clearSqsMessages();
9694
}
9795

@@ -532,15 +530,9 @@ public void testPost12() throws ApiException, InterruptedException {
532530
assertNull(response.getUploadUrl());
533531
String documentId = response.getDocumentId();
534532

535-
List<Message> sqsMessages = getSqsMessages();
536-
assertEquals(1, sqsMessages.size());
537-
538-
Map<String, String> map =
539-
GsonUtil.getInstance().fromJson(sqsMessages.get(0).body(), Map.class);
540-
541-
map = GsonUtil.getInstance().fromJson(map.get("Message"), Map.class);
542-
assertEquals(documentId, map.get("documentId"));
543-
assertEquals("actions", map.get("type"));
533+
Map<String, Object> message = getSqsMessages("actions", documentId);
534+
assertEquals("actions", message.get("type"));
535+
assertEquals(documentId, message.get("documentId"));
544536
}
545537
}
546538

@@ -550,7 +542,7 @@ public void testPost12() throws ApiException, InterruptedException {
550542
*/
551543
@Test
552544
@Timeout(TEST_TIMEOUT)
553-
public void testPost13() throws ApiException, InterruptedException {
545+
public void testPost13() throws ApiException {
554546
// given
555547
for (String siteId : Arrays.asList("default", UUID.randomUUID().toString())) {
556548

@@ -580,7 +572,7 @@ public void testPost13() throws ApiException, InterruptedException {
580572
*/
581573
@Test
582574
@Timeout(TEST_TIMEOUT)
583-
public void testPost14() throws InterruptedException {
575+
public void testPost14() {
584576
// given
585577
for (String siteId : Arrays.asList("default", UUID.randomUUID().toString())) {
586578

@@ -761,7 +753,7 @@ public void testPost18() throws Exception {
761753
*/
762754
@Test
763755
@Timeout(TEST_TIMEOUT)
764-
public void testPost19() throws ApiException, InterruptedException {
756+
public void testPost19() {
765757
// given
766758
for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
767759

0 commit comments

Comments
 (0)