Skip to content

Commit 292b4e0

Browse files
committed
PS-1575: Daily cleanup for in-memory H2 DB to avoid OOM
1 parent 28f90ff commit 292b4e0

File tree

6 files changed

+91
-45
lines changed

6 files changed

+91
-45
lines changed

src/main/java/org/test/consumer/domain/EventMessage.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package org.test.consumer.domain;
22

3+
import java.time.LocalDateTime;
4+
import javax.persistence.Column;
5+
import javax.persistence.Entity;
6+
import javax.persistence.GeneratedValue;
7+
import javax.persistence.GenerationType;
8+
import javax.persistence.Id;
9+
import javax.persistence.Lob;
10+
import javax.persistence.Table;
311
import lombok.Getter;
412
import lombok.NoArgsConstructor;
513

6-
import javax.persistence.*;
7-
814
@Entity
915
@Table(name="event_message")
1016
@Getter
1117
@NoArgsConstructor
1218
public class EventMessage {
1319
@Id
14-
@GeneratedValue(strategy = GenerationType.AUTO)
20+
@GeneratedValue(strategy = GenerationType.IDENTITY)
1521
private int id;
1622
@Column(name="event_id")
1723
private int eventId;
@@ -24,14 +30,14 @@ public class EventMessage {
2430
@Column(name="tenant_id")
2531
private String tenantId;
2632
@Column(name="created_at")
27-
private String createdAt;
33+
private LocalDateTime createdAt;
2834
@Lob
2935
@Column(name="payload", columnDefinition="BLOB")
3036
private byte[] payload;
3137
@Column(name="business_date")
3238
private String businessDate;
3339

34-
public EventMessage(int eventId, String type, String category, String schema, String tenantId, String createdAt, byte[] payload, String businessDate) {
40+
public EventMessage(int eventId, String type, String category, String schema, String tenantId, LocalDateTime createdAt, byte[] payload, String businessDate) {
3541
this.eventId = eventId;
3642
this.type = type;
3743
this.category = category;
Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package org.test.consumer.handler;
22

3+
import java.io.IOException;
4+
import java.nio.ByteBuffer;
5+
import java.time.LocalDateTime;
6+
import java.time.format.DateTimeFormatter;
7+
import lombok.extern.slf4j.Slf4j;
38
import org.apache.fineract.avro.MessageV1;
4-
import org.slf4j.Logger;
5-
import org.slf4j.LoggerFactory;
69
import org.springframework.beans.factory.annotation.Autowired;
710
import org.springframework.messaging.Message;
811
import org.springframework.messaging.MessageHandler;
@@ -12,36 +15,32 @@
1215
import org.test.consumer.repository.EventMessageRepository;
1316
import org.test.consumer.utility.ByteBufferConvertor;
1417

15-
import java.io.IOException;
16-
import java.nio.ByteBuffer;
17-
1818

1919
@Component
20+
@Slf4j
2021
public class JMSMessageConsumerHandler implements MessageHandler {
21-
private static final Logger logger = LoggerFactory.getLogger(JMSMessageConsumerHandler.class);
22-
2322
@Autowired
2423
private ByteBufferConvertor byteBufferConvertor;
2524

2625
@Autowired
2726
private EventMessageRepository repository;
2827

2928
@Override
30-
public void handleMessage(Message<?> message) throws MessagingException{
31-
ByteBuffer messageByteBuffer = byteBufferConvertor.convert((byte [] )message.getPayload());
32-
MessageV1 messagePayload = null;
29+
public void handleMessage(Message<?> message) throws MessagingException {
30+
ByteBuffer messageByteBuffer = byteBufferConvertor.convert((byte[]) message.getPayload());
3331
try {
34-
messagePayload = MessageV1.fromByteBuffer(messageByteBuffer);
32+
MessageV1 messagePayload = MessageV1.fromByteBuffer(messageByteBuffer);
33+
log.info("Received message for event of Category = {}, Type = {}", messagePayload.getCategory(), messagePayload.getType());
34+
saveMessage(messagePayload);
3535
} catch (IOException e) {
36-
logger.error("Unable to read message {}",e);
36+
log.error("Unable to read message", e);
3737
}
38-
logger.info("Received message for event of Category = {}, Type = {}",messagePayload.getCategory(), messagePayload.getType());
39-
saveMessage(messagePayload);
4038
}
4139

42-
private void saveMessage(MessageV1 messagePayload){
43-
EventMessage message = new EventMessage(messagePayload.getId(),messagePayload.getType(),messagePayload.getCategory(),messagePayload.getDataschema(),messagePayload.getTenantId(),messagePayload.getCreatedAt(),byteBufferConvertor.convert(messagePayload.getData()),
44-
messagePayload.getBusinessDate());
40+
private void saveMessage(MessageV1 messagePayload) {
41+
LocalDateTime createdAt = LocalDateTime.parse(messagePayload.getCreatedAt(), DateTimeFormatter.ISO_DATE_TIME);
42+
EventMessage message = new EventMessage(messagePayload.getId(), messagePayload.getType(), messagePayload.getCategory(), messagePayload.getDataschema(), messagePayload.getTenantId(), createdAt, byteBufferConvertor.convert(messagePayload.getData()),
43+
messagePayload.getBusinessDate());
4544
repository.save(message);
4645
}
4746
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.test.consumer.job;
2+
3+
import java.time.Clock;
4+
import java.time.LocalDate;
5+
import java.time.LocalDateTime;
6+
import javax.persistence.EntityManager;
7+
import javax.persistence.criteria.CriteriaBuilder;
8+
import javax.persistence.criteria.CriteriaDelete;
9+
import javax.persistence.criteria.Root;
10+
import lombok.RequiredArgsConstructor;
11+
import lombok.extern.slf4j.Slf4j;
12+
import org.springframework.scheduling.annotation.Scheduled;
13+
import org.springframework.stereotype.Component;
14+
import org.springframework.transaction.annotation.Transactional;
15+
import org.test.consumer.domain.EventMessage;
16+
17+
@Component
18+
@RequiredArgsConstructor
19+
@Slf4j
20+
public class PurgeOldEventsJob {
21+
private final EntityManager entityManager;
22+
23+
@Scheduled(cron = "0 0 * * *")
24+
@Transactional
25+
public void purge() {
26+
log.info("Starting the purging");
27+
LocalDateTime todayStartOfDay = LocalDate.now(Clock.systemUTC()).atStartOfDay();
28+
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
29+
CriteriaDelete<EventMessage> deleteQ = cb.createCriteriaDelete(EventMessage.class);
30+
Root<EventMessage> from = deleteQ.from(EventMessage.class);
31+
deleteQ.where(cb.lessThan(from.get("createdAt"), todayStartOfDay));
32+
33+
entityManager.createQuery(deleteQ).executeUpdate();
34+
log.info("Purging finished");
35+
}
36+
}

src/main/java/org/test/consumer/service/MessageConsumerServiceImpl.java

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
package org.test.consumer.service;
22

3+
import java.lang.reflect.InvocationTargetException;
4+
import java.lang.reflect.Method;
5+
import java.nio.ByteBuffer;
6+
import java.time.format.DateTimeFormatter;
7+
import java.util.ArrayList;
8+
import java.util.List;
39
import lombok.AllArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
411
import org.apache.fineract.avro.BulkMessageItemV1;
5-
import org.slf4j.Logger;
6-
import org.slf4j.LoggerFactory;
712
import org.springframework.stereotype.Service;
813
import org.test.consumer.data.EventMessageDTO;
914
import org.test.consumer.domain.EventMessage;
1015
import org.test.consumer.repository.EventMessageRepository;
1116
import org.test.consumer.utility.ByteBufferConvertor;
1217

13-
import java.lang.reflect.InvocationTargetException;
14-
import java.lang.reflect.Method;
15-
import java.nio.ByteBuffer;
16-
import java.util.ArrayList;
17-
import java.util.List;
18-
1918
@Service
2019
@AllArgsConstructor
20+
@Slf4j
2121
public class MessageConsumerServiceImpl implements MessageConsumerService {
22-
23-
private static final Logger logger = LoggerFactory.getLogger(MessageConsumerServiceImpl.class);
24-
2522
private final EventMessageRepository repository;
2623
private final ByteBufferConvertor byteBufferConvertor;
2724

@@ -31,8 +28,9 @@ public List<EventMessageDTO> getMessages() {
3128
List<EventMessage> messages = repository.findAll();
3229
try {
3330
eventMessages = convertToReadableFormat(messages);
34-
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
35-
logger.error("Unable to read message {}", e);
31+
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
32+
IllegalAccessException e) {
33+
log.error("Unable to read message", e);
3634
}
3735
return eventMessages;
3836
}
@@ -43,8 +41,9 @@ public List<EventMessageDTO> getMessagesByType(String eventType) {
4341
List<EventMessage> messages = repository.findByType(eventType);
4442
try {
4543
eventMessages = convertToReadableFormat(messages);
46-
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
47-
logger.error("Unable to read message {}", e);
44+
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
45+
IllegalAccessException e) {
46+
log.error("Unable to read message", e);
4847
}
4948
return eventMessages;
5049
}
@@ -55,7 +54,7 @@ public void deleteMessages() {
5554
}
5655

5756
private List<EventMessageDTO> convertToReadableFormat(List<EventMessage> messages)
58-
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
57+
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
5958
List<EventMessageDTO> eventMessages = new ArrayList<>();
6059
for (EventMessage message : messages) {
6160
Class payLoadClass = Class.forName(message.getSchema());
@@ -71,22 +70,26 @@ private List<EventMessageDTO> convertToReadableFormat(List<EventMessage> message
7170
bulkMessagePayload.append(bulkMessageData);
7271
bulkMessagePayload.append(System.lineSeparator());
7372
}
74-
eventMessages.add(new EventMessageDTO(message.getEventId(), message.getType(), message.getCategory(), message.getTenantId(), message.getCreatedAt(),
75-
bulkMessagePayload.toString(),
76-
message.getBusinessDate()));
73+
eventMessages.add(new EventMessageDTO(message.getEventId(), message.getType(), message.getCategory(), message.getTenantId(), getCreatedAt(message),
74+
bulkMessagePayload.toString(),
75+
message.getBusinessDate()));
7776

7877
} else {
7978
eventMessages.add(
80-
new EventMessageDTO(message.getEventId(), message.getType(), message.getCategory(), message.getTenantId(), message.getCreatedAt(), payLoad.toString(),
81-
message.getBusinessDate()));
79+
new EventMessageDTO(message.getEventId(), message.getType(), message.getCategory(), message.getTenantId(), getCreatedAt(message), payLoad.toString(),
80+
message.getBusinessDate()));
8281
}
8382
}
8483

8584
return eventMessages;
8685
}
8786

87+
private String getCreatedAt(EventMessage message) {
88+
return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(message.getCreatedAt());
89+
}
90+
8891
private EventMessageDTO retrieveBulkMessage(BulkMessageItemV1 messageItem)
89-
throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException {
92+
throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException {
9093
Class messageBulkMessagePayLoad = Class.forName(messageItem.getDataschema());
9194
Method methodForPayLoad = messageBulkMessagePayLoad.getMethod("fromByteBuffer", ByteBuffer.class);
9295
Object payLoadBulkItem = methodForPayLoad.invoke(null, messageItem.getData());

src/main/resources/application.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ spring.datasource.username=sa
66
spring.datasource.password=
77
spring.datasource.driverClassName=org.h2.Driver
88
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
9+
spring.jpa.hibernate.ddl-auto=validate
10+

src/main/resources/schema.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CREATE TABLE event_message (
44
event_id INT NOT NULL,
55
type VARCHAR(100) NOT NULL,
66
data_schema VARCHAR(200) NOT NULL,
7-
created_at VARCHAR(100),
7+
created_at TIMESTAMP WITHOUT TIME ZONE,
88
tenant_id VARCHAR(100),
99
payload BLOB NOT NULL,
1010
category VARCHAR(100) NOT NULL,

0 commit comments

Comments
 (0)