My problem is that even if I take ping etc. into account, the following API request takes 10 times longer in my production environment(remote database(AWS), docker, etc.) with the same amount of data. It takes around 150ms when I run it on localhost and 1.5-2s when I run it on production. What might cause that huge difference? Like I said its the same amount of data, the ping, and the traffic transmitted(only 5kb) shouldn't cause that. I also only have two SQL queries I manually call. A lot of more SQL queries are automatically called because of the OneToMany
relation you can see below. But I can't think of why that would cause any difference in performance between localhost and production.
Thats the API method i call:
@GetMapping
public ResponseEntity<List<Project>> getProjects(@RequestParam(required = false) boolean additionalInfo) {
return ResponseEntity.ok(projectService.getProjects(additionalInfo));
}
Inside the service:
private List<Project> getProjects(boolean additionalInfo) {
List<Project> projects = (List<Project>) projectRepository.findAll();
if (additionalInfo) {
for (Project project : projects) {
setAdditionalInfo(project);
}
}
return projects;
}
private void setAdditionalInfo(Project project) {
Integer notificationCount = 0;
Duration duration = Duration.ZERO;
LocalDate lastDailyEntryDate = LocalDate.MIN;
for (DailyEntry dailyEntry : dailyEntryRepository.findByProjectId(project.getId())) {
if (dailyEntry.getStatus().equals(EntryStatus.OPEN)) {
notificationCount++;
}
duration = duration.plus(Duration.between(dailyEntry.getStartTime(), dailyEntry.getEndTime()));
if (lastDailyEntryDate.isBefore(dailyEntry.getDate())) {
lastDailyEntryDate = dailyEntry.getDate();
}
}
int inactiveSince = calculateInactiveSince(lastDailyEntryDate, project);
if (inactiveSince >= 3 && !project.getIsArchived()) {
project.setInactiveSince(inactiveSince);
}
project.setNotificationCount(notificationCount);
project.setUsedBudget(duration.toHours() * 100);
}
private Integer calculateInactiveSince(LocalDate lastDailyEntryDate, Project project) {
int inactiveSince;
if (lastDailyEntryDate != LocalDate.MIN) {
Period period = Period.between(lastDailyEntryDate, LocalDate.now());
inactiveSince = period.getYears() * 12 + period.getMonths();
} else {
Period period = Period.between(project.getCreationDate(), LocalDate.now());
inactiveSince = period.getYears() * 12 + period.getMonths();
}
return inactiveSince;
}
Thats how the entites look like:
Project:
@Data
@Entity
@ToString(exclude = {"employees"})
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Project {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(unique = true)
private String name;
private Integer budget;
private String description;
private Boolean isArchived;
private LocalDate archivedDate;
private LocalDate creationDate;
@NotNull
@ManyToOne
private Customer customer;
@ManyToMany
@JoinTable(
name = "employee_projects",
joinColumns = @JoinColumn(name = "project_id"),
inverseJoinColumns = @JoinColumn(name = "employee_id")
)
private List<Employee> employees;
@Transient
private Long usedBudget;
@Transient
private Integer notificationCount;
@Transient
private Boolean isInactive;
@Transient
private Integer inactiveSince;
}
DailyEntry:
@Data
@Entity
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DailyEntry {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private LocalDate date;
private LocalTime startTime;
private LocalTime endTime;
private Duration breaks;
private String performanceRecord;
private EntryStatus status;
@ManyToOne
private Project project;
@ManyToOne
private Employee employee;
}