Skip to content

Commit a314f28

Browse files
committed
feat:added history logic aand connect redis
1 parent 737e3c0 commit a314f28

File tree

11 files changed

+310
-0
lines changed

11 files changed

+310
-0
lines changed

service/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@
3131
<groupId>org.springframework.boot</groupId>
3232
<artifactId>spring-boot-starter-data-jpa</artifactId>
3333
</dependency>
34+
<dependency>
35+
<groupId>org.springframework.boot</groupId>
36+
<artifactId>spring-boot-starter-data-redis</artifactId>
37+
</dependency>
38+
<dependency>
39+
<groupId>org.mockito</groupId>
40+
<artifactId>mockito-core</artifactId>
41+
<version>5.12.0</version>
42+
<scope>test</scope>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.mockito</groupId>
46+
<artifactId>mockito-junit-jupiter</artifactId>
47+
<version>5.12.0</version>
48+
<scope>test</scope>
49+
</dependency>
3450
<!-- <dependency>-->
3551
<!-- <groupId>org.postgresql</groupId>-->
3652
<!-- <artifactId>postgresql</artifactId>-->
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package service.task.manager.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.data.redis.connection.RedisConnectionFactory;
6+
import org.springframework.data.redis.core.RedisTemplate;
7+
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
8+
import service.task.manager.model.HistoryEntry;
9+
10+
@Configuration
11+
public class RedisConfig {
12+
13+
@Bean
14+
public RedisTemplate<String, HistoryEntry> redisTemplate(RedisConnectionFactory connectionFactory) {
15+
RedisTemplate<String, HistoryEntry> template = new RedisTemplate<>();
16+
template.setConnectionFactory(connectionFactory);
17+
template.setDefaultSerializer(new Jackson2JsonRedisSerializer<>(HistoryEntry.class));
18+
return template;
19+
}
20+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package service.task.manager.controller;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.media.ArraySchema;
5+
import io.swagger.v3.oas.annotations.media.Content;
6+
import io.swagger.v3.oas.annotations.media.Schema;
7+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
8+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
9+
import io.swagger.v3.oas.annotations.tags.Tag;
10+
import lombok.RequiredArgsConstructor;
11+
import lombok.extern.slf4j.Slf4j;
12+
import org.springframework.web.bind.annotation.CrossOrigin;
13+
import org.springframework.web.bind.annotation.GetMapping;
14+
import org.springframework.web.bind.annotation.RequestMapping;
15+
import org.springframework.web.bind.annotation.RestController;
16+
import service.task.manager.model.HistoryEntry;
17+
import service.task.manager.service.HistoryService;
18+
19+
import java.util.List;
20+
21+
/**
22+
* Controller for managing and retrieving the history of task accesses.
23+
*/
24+
@Slf4j
25+
@CrossOrigin
26+
@RestController
27+
@RequiredArgsConstructor
28+
@RequestMapping("/history")
29+
@Tag(name = "History API", description = "API for retrieving the history of task accesses")
30+
public class HistoryController {
31+
32+
private final HistoryService service;
33+
34+
/**
35+
* Retrieves the history of task accesses.
36+
* The history contains the last 10 records of calls to the findBy(long id) method for tasks, epics, and subtasks.
37+
*
38+
* @return a list of history entries
39+
*/
40+
@GetMapping
41+
@Operation(summary = "Get task access history", description = "Retrieves the history of the last 10 task accesses (Task, Epic, Subtask) made via the findBy(long id) method.")
42+
@ApiResponses(value = {
43+
@ApiResponse(responseCode = "200", description = "History retrieved successfully",
44+
content = @Content(mediaType = "application/json",
45+
array = @ArraySchema(schema = @Schema(implementation = HistoryEntry.class)))),
46+
@ApiResponse(responseCode = "500", description = "Internal server error, possibly due to Redis connectivity issues",
47+
content = @Content)
48+
})
49+
public List<HistoryEntry> getHistory() {
50+
try {
51+
log.info("Received request to retrieve task access history");
52+
List<HistoryEntry> history = service.getHistory();
53+
log.debug("Successfully retrieved history with {} entries", history.size());
54+
return history;
55+
} catch (Exception e) {
56+
log.error("Failed to retrieve task access history: {}", e.getMessage(), e);
57+
throw new RuntimeException("Failed to retrieve history", e);
58+
}
59+
}
60+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package service.task.manager.model;
2+
3+
import lombok.*;
4+
import service.task.manager.model.enums.TaskType;
5+
6+
@AllArgsConstructor
7+
@NoArgsConstructor
8+
@Getter
9+
@Setter
10+
@ToString
11+
public class HistoryEntry {
12+
private TaskType type;
13+
private Long id;
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package service.task.manager.service;
2+
3+
import service.task.manager.model.HistoryEntry;
4+
import service.task.manager.model.enums.TaskType;
5+
6+
import java.util.List;
7+
8+
public interface HistoryService {
9+
10+
void addToHistory(TaskType type, Long id);
11+
12+
List<HistoryEntry> getHistory();
13+
}

service/src/main/java/service/task/manager/service/impl/EpicServiceImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import service.task.manager.model.enums.Status;
1515
import service.task.manager.repository.EpicRepository;
1616
import service.task.manager.service.EpicService;
17+
import service.task.manager.service.HistoryService;
1718

1819
import java.util.List;
1920

@@ -27,6 +28,7 @@
2728
public class EpicServiceImpl implements EpicService {
2829
private final EpicRepository repository;
2930
private final EpicMapper mapper;
31+
private final HistoryService history;
3032

3133
/**
3234
* Creates a new epic based on the provided DTO.
@@ -92,6 +94,7 @@ public EpicResponseDto findById(Long id) {
9294
log.warn("Epic with ID {} not found", id);
9395
return new NotFoundException("Epic with ID " + id + " not found");
9496
});
97+
history.addToHistory(epic.type(), epic.id());
9598
log.info("Epic with ID {} retrieved successfully", id);
9699
return epic;
97100
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package service.task.manager.service.impl;
2+
3+
import jakarta.annotation.PostConstruct;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.extern.slf4j.Slf4j;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.data.redis.core.ListOperations;
8+
import org.springframework.data.redis.core.RedisTemplate;
9+
import org.springframework.stereotype.Service;
10+
import service.task.manager.model.HistoryEntry;
11+
import service.task.manager.model.enums.TaskType;
12+
import service.task.manager.service.HistoryService;
13+
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
17+
/**
18+
* Implementation of the service for managing the history of accesses to tasks (Task, Epic, Subtask) using Redis.
19+
* The history stores the last 10 records of calls to the findBy(long id) method for tasks, epics, and subtasks.
20+
* If the number of records exceeds the limit, the oldest record is removed.
21+
*/
22+
@Slf4j
23+
@Service
24+
public class HistoryServiceImpl implements HistoryService {
25+
26+
private static final String HISTORY_KEY = "history";
27+
private static final int HISTORY_SIZE = 10;
28+
29+
private final RedisTemplate<String, HistoryEntry> redisTemplate;
30+
private final ListOperations<String, HistoryEntry> listOps;
31+
32+
@Autowired
33+
public HistoryServiceImpl(RedisTemplate<String, HistoryEntry> redisTemplate) {
34+
this.redisTemplate = redisTemplate;
35+
this.listOps = redisTemplate.opsForList();
36+
}
37+
38+
/**
39+
* Adds a record to the history of findBy(long id) method calls.
40+
* If the history size exceeds the limit (10 records), the oldest record is removed.
41+
*
42+
* @param type the type of the task (TASK, EPIC, SUBTASK)
43+
* @param id the identifier of the task
44+
*/
45+
@Override
46+
public void addToHistory(TaskType type, Long id) {
47+
try {
48+
HistoryEntry entry = new HistoryEntry(type, id);
49+
log.info("Adding entry to history: type={}, id={}", type, id);
50+
listOps.rightPush(HISTORY_KEY, entry);
51+
Long size = listOps.size(HISTORY_KEY);
52+
if (size != null && size > HISTORY_SIZE) {
53+
log.debug("History size exceeded limit ({}), removing oldest entry", HISTORY_SIZE);
54+
listOps.leftPop(HISTORY_KEY);
55+
}
56+
} catch (Exception e) {
57+
log.error("Failed to add entry to history: type={}, id={}, error={}", type, id, e.getMessage(), e);
58+
}
59+
}
60+
61+
/**
62+
* Retrieves the list of entries from the history of method calls.
63+
* If the history is empty or an error occurs while retrieving data, an empty list is returned.
64+
*
65+
* @return the list of history entries
66+
*/
67+
@Override
68+
public List<HistoryEntry> getHistory() {
69+
try {
70+
log.info("Retrieving call history");
71+
List<HistoryEntry> history = listOps.range(HISTORY_KEY, 0, -1);
72+
if (history == null) {
73+
log.warn("History is empty or failed to retrieve data from Redis");
74+
return new ArrayList<>();
75+
}
76+
log.debug("Successfully retrieved {} entries from history", history.size());
77+
return history;
78+
} catch (Exception e) {
79+
log.error("Failed to retrieve history: {}", e.getMessage(), e);
80+
return new ArrayList<>();
81+
}
82+
}
83+
}

service/src/main/java/service/task/manager/service/impl/SubtaskServiceImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import service.task.manager.model.enums.Status;
1818
import service.task.manager.repository.SubtaskRepository;
1919
import service.task.manager.service.EpicService;
20+
import service.task.manager.service.HistoryService;
2021
import service.task.manager.service.SubtaskService;
2122

2223
import java.util.List;
@@ -33,6 +34,7 @@ public class SubtaskServiceImpl implements SubtaskService {
3334
private final EpicService epicService;
3435
private final SubtaskMapper mapper;
3536
private final EpicMapper epicMapper;
37+
private final HistoryService history;
3638

3739
/**
3840
* Creates a new subtask based on the provided DTO.
@@ -103,6 +105,7 @@ public SubtaskResponseDto findById(Long id) {
103105
log.warn("Subtask with ID {} not found", id);
104106
return new NotFoundException("Subtask with ID " + id + " not found");
105107
});
108+
history.addToHistory(subtask.type(),subtask.id());
106109
log.info("Subtask with ID {} retrieved successfully", id);
107110
return subtask;
108111
}

service/src/main/java/service/task/manager/service/impl/TaskServiceImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import service.task.manager.model.Task;
1414
import service.task.manager.model.enums.Status;
1515
import service.task.manager.repository.TaskRepository;
16+
import service.task.manager.service.HistoryService;
1617
import service.task.manager.service.TaskService;
1718

1819
import java.util.List;
@@ -27,6 +28,7 @@
2728
public class TaskServiceImpl implements TaskService {
2829
private final TaskRepository repository;
2930
private final TaskMapper mapper;
31+
private final HistoryService history;
3032

3133
/**
3234
* Creates a new task based on the provided DTO.
@@ -81,6 +83,7 @@ public TaskResponseDto findById(Long id) {
8183
log.warn("Task with ID {} not found", id);
8284
return new NotFoundException("Task with ID " + id + " not found");
8385
});
86+
history.addToHistory(task.type(),task.id());
8487
log.info("Task with ID {} retrieved successfully", id);
8588
return task;
8689
}

service/src/main/resources/application.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ spring:
1111
jpa:
1212
properties:
1313
hibernate.dialect: org.hibernate.dialect.H2Dialect
14+
data:
15+
redis:
16+
host: localhost
17+
port: 6379
1418

1519
# Путь к Swagger UI
1620
springdoc:

0 commit comments

Comments
 (0)