Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 동방 현황 기능을 구현합니다. #145

Merged
merged 111 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
f720bcd
refactor(api): Exception 컨벤션 적용
Jan 4, 2025
c00bcc8
Merge branch 'develop' of https://github.com/JNU-econovation/Whoz-in-…
Jan 4, 2025
fd9aeae
feat(domain): Active 상태인 Device에 관련된 인터페이스 추가
Jan 5, 2025
e186fe5
feat(main-api): application Event 관련 설정 추가
Jan 5, 2025
5094c78
feat(main-api): ActiveDevice 이벤트 추가
Jan 5, 2025
072c6a1
feat(main-api): DeviceRepository 메소드 추가
Jan 5, 2025
7616d72
feat(main-api): ActiveDevice 관련 Response 추가
Jan 5, 2025
fe19d03
feat(api-query-jpa): Device 엔티티 추가
Jan 5, 2025
9f6498e
feat(api-query-jpa): MemberRepository 메소드 추가
Jan 5, 2025
6534057
feat(api-query-jpa): activeDevice 관련된 view , viewer 정의
Jan 5, 2025
d1bbb6c
delete(main-api): main api에 있는 ActiveDeviceEventHandler 삭제
Jan 5, 2025
a0a4370
feat(api-query-jpa): api-query-jpa 모듈에 ActiveDeviceEventHandler 정의
Jan 5, 2025
8ddc7e0
feat(api-query-jpa): ActiveDeviceEntity 정의 및 레포지토리 정의
Jan 5, 2025
3e48fe1
feat(api-query-jpa): ActiveDeviceJpaViewer 정의
Jan 5, 2025
0164825
refactor(main-api): device/active 패키지로 이동
Jan 6, 2025
b1cfcec
delete(main-api): 패키지 이동에 따른 삭제
Jan 6, 2025
adaa5b1
refactor(api-query-jpa): findAll 메소드 필터 설정
Jan 7, 2025
8b04717
refactor(domain): ActiveDeviceFinder 메소드 추가 및 변경
Jan 7, 2025
5391f51
feat(main-api): ActiveDeviceFinder 인터페이스 구현
Jan 7, 2025
85c739c
feat(api-query-jpa): ActiveDeviceEventHandler 구현
Jan 7, 2025
110f513
refactor(api-query-jpa): ActiveDeviceEntity 메소드명 오타 수정
Jan 7, 2025
94fa8e1
feat(domain-jpa): MonitorLogEntityRepository 메소드 추가
Jan 7, 2025
28a0a5c
feat(main-api): ActiveDeviceFinded에 필드 추가
Jan 7, 2025
072274f
feat(domain-jpa): MonitorLogRepository 메소드 추가 및 구현
Jan 7, 2025
7ba0a2b
feat(main-api): InActiveDeviceFinded 이벤트 정의
Jan 7, 2025
9e49465
refactor(domain): 인터페이스명 변경
Jan 7, 2025
fd0dbaa
refactor(main-api): SpringActiveDeviceFinder 이름 변경
Jan 7, 2025
58d11b1
refactor(main-api,api-query-jpa): api-query-jpa 가 domain 을 의존하는 문제 해결
Jan 7, 2025
9417b27
refactor(api-query-jpa): ActiveDeviceEventHandler 클래스명 변경
Jan 7, 2025
42b163d
refactor(api-query-jpa): 사용하지 않는 메소드 삭제
Jan 7, 2025
64660c1
feat(main-api): 스케줄링 설정 추가
Jan 7, 2025
c22083a
delete(domain): 사용하지 않는 인터페이스 제거
Jan 7, 2025
e387f7f
delete(api-query-jpa): 사용하지 않는 인터페이스 제거
Jan 7, 2025
378d08a
refactor(api-query-jpa): SubSelect 를 native 쿼리로 변경
Jan 7, 2025
2443cb8
refactor(api-query-jpa): Device 파라미터 설정 및 수정된 필드 적용
Jan 7, 2025
3224d9b
refactor(api-query-jpa): ActiveDevice InMemory 데이터베이스로 구현
Jan 7, 2025
6446648
comment(api-query-jpa): TODO 추가
Jan 7, 2025
91ff2af
refactor(main-api): 패키지 이동
Jan 7, 2025
b09685e
feat(main-api): Active InActive Device의 상태를 판별하는 Device 필터 작성
Jan 8, 2025
38878e7
feat(main-api): Active InActive 필터 작성
Jan 8, 2025
0bba87a
refactor(main-api): DeviceFilter 사용
Jan 8, 2025
f3c8c73
pull develop branch (충돌 해결)
Jan 8, 2025
b9bdf9b
refactor(api-query-jpa): 이벤트 타입 미스매치 해결
Jan 8, 2025
37d03b6
feat(api-query-jpa): Member에 name 필드 추가
Jan 8, 2025
3bde4a5
feat(main-api,api-query-jpa): MemberName 을 조회하기 위한 View 작성 및 구현
Jan 8, 2025
e27fcd6
feat(main-api,api-query-jpa): ActiveDevice View에 totalConnectedTime 추가
Jan 8, 2025
3ceb327
feat(main-api): DeviceController 작성 및 ActiveDeviceListHandler 구현
Jan 8, 2025
2c161b5
feat(main-api): memberName 조회 코드 추가
Jan 8, 2025
77ca3a2
refactor(main-api): ActiveDeviceListHandler 빈 리스트일 경우 분기 처리
Jan 8, 2025
0f97e1d
refactor(main-api): ResponseEntityGenerator 사용
Jan 8, 2025
908fed4
refactor(api-query-jpa): @Column 어노테이션으로 테이블 열 매핑
Jan 8, 2025
1b4c553
refactor(main-api): page 숫자 - 1
Jan 8, 2025
24e14ac
refactor(main-api): GlobalExceptionHandler에서 에러 로그 출력
Jan 8, 2025
b8410b2
refactor(main-api): null 값 처리
Jan 8, 2025
76061f6
Merge branch 'develop' into feat/119
rlajm1203 Jan 8, 2025
e0612b0
feat(main-api): totalConnectedTime, continuousTime 메소드 추가
Jan 8, 2025
18760f4
refactor(api-query-jpa): save 메소드 변경
Jan 8, 2025
28e4fc6
feat(main-api): 동병 현황 조회 api 허용 추가
Jan 8, 2025
570395b
refactor(main-api): ActiveDeviceListHandler 시간 계산 로직 수정
Jan 8, 2025
a4070e1
refactor(network-api): room-setting 으로 변경
Jan 8, 2025
3605bf6
refactor(network-api): room-setting 으로 변경
Jan 8, 2025
de4bd02
pull conflict resolved
Jan 8, 2025
08e3c9e
refactor(domain): 필요 없는 메소드 삭제
Jan 8, 2025
6f20675
refactor(main-api): 클래스 이름 변경
Jan 8, 2025
9600edf
refactor(main-api,api-query-jpa): isActive 필드 추가
Jan 8, 2025
0f29b37
refactor(main-api,api-query-jpa): isActive 필드 추가
Jan 8, 2025
81d099c
refactor(main-api): monitorLog 10분 전 로그들로만 조회
Jan 8, 2025
9060b6e
refactor(api-query-jpa): ConcurrentHashMap 으로 변경
Jan 8, 2025
0ac2341
refactor(api-query-jpa): 격리 수준 default 설정
Jan 8, 2025
cc71c6b
refactor(main-api): 전체적인 코드 리팩토링
Jan 8, 2025
817b548
refactor(main-api): 로그 문구 수정
Jan 8, 2025
e6c1c45
refactor(api-query-jpa): totalActiveTime이 null 일 경우 처리
Jan 8, 2025
656a091
refactor(api-query-jpa): 격리 수중 최강으로 변경
Jan 8, 2025
e06e576
test(main-api): viewerTest 추가
Jan 9, 2025
5e9f2ab
comment(main-api): 주석 추가
Jan 9, 2025
00905bf
refactor(main-api): DeviceFilter execute 로직 수정
Jan 9, 2025
aabb2b1
refactor(main-api): ActiveDeviceFinded 필드 수정
Jan 9, 2025
ac334ec
feat(main-api): ActiveDeviceFilter 구현
Jan 9, 2025
a7624b0
refactor(main-api): getUniqueMonitorLogs 메소드 이전
Jan 9, 2025
7ac306c
refactor(main-api): Filter 사용으로 변경
Jan 9, 2025
d6fb453
feat(main-api): InActiveDeviceFilter 구현
Jan 9, 2025
e5bcc61
refactor(main-api): ActiveDeviceFilter 로직 수정
Jan 9, 2025
d487221
comment(main-api): DeviceFilter 코멘트 추가
Jan 9, 2025
59af952
refactor(api-query-jpa): 갱신된 데이터 삽입 가능하도록 변경
Jan 9, 2025
df0a5ef
refactor(main-api): ActiveDeviceFilter, InActiveDeviceFilter 로직 변경
Jan 9, 2025
3049624
comment(main-api): DeviceFilter TODO 추가
Jan 9, 2025
c31977f
refactor(main-api): MonitorLog 가 없을 경우 바로 리턴
Jan 9, 2025
8bf47fa
feat(api-query-jpa): DeviceEventHandler 수정
Jan 9, 2025
6c2b7f7
refactor(main-api): 로그 문구 수정 및 inActive 판별 로직 수정
Jan 9, 2025
edbbf93
refactor(api-query-jpa): ActiveDeviceEntity activeOn 메소드 수정
Jan 9, 2025
c76b88a
refactor(api-query-jpa): ActiveDeviceEntity addTotalActiveTime 메소드 수정
Jan 9, 2025
717b33b
refactor(main-api): ActiveDevice View 시간 계산 로직 수정
Jan 9, 2025
76e41c4
refactor(main-api): return 추가
Jan 9, 2025
5fd7c83
refactor(main-api): total 시간 계산 로직 수정
Jan 9, 2025
3680b05
comment(main-api): 불필요한 주석 제거
Jan 9, 2025
312c635
refactor(main-api): 연속 접속 시간, 누적 접속 시간 시간 계산 로직 수정
Jan 10, 2025
2628e0b
Merge branch 'develop' of https://github.com/JNU-econovation/Whoz-in-…
Jan 10, 2025
b6b3293
refactor(main-api): 처음으로 active 상태가 된 기기일 경우 로그 수준 info 로 변경
Jan 13, 2025
0a77906
comment(main-api): 주석 수정
Jan 13, 2025
1253b3f
refactor(main-api): monitorLog 현재로부터 10분 이전 로그 조회, InActive 판별 기준 10분…
Jan 13, 2025
78dfba6
refactor(main-api): 첫 Active 상태 전환이 아님을 판별하는 로직 수정
Jan 13, 2025
dc00d84
refactor(api-query-jpa): ddlAuto , namingStrategy 속성 값 변경
Jan 15, 2025
df0cbcb
refactor(api-query-jpa): 필드명 변경
Jan 15, 2025
3208c54
refactor(api-query-jpa): ActiveDevice JPA 적용
Jan 15, 2025
fd6409b
fix(api-query-jpa): api query jpa config hibernate 오타 수정
Jan 15, 2025
dbe38e1
refactor(api-query-jpa): JPA 적용
Jan 15, 2025
4d151a7
chore(github): 코드 리뷰용 커밋
Jan 15, 2025
235ae31
Merge branch 'develop' into feat/119
rlajm1203 Jan 15, 2025
dccef6f
fix(api-query-jpa): 세미콜론 추가
Jan 15, 2025
93c2dca
Merge pull request #167 from JNU-econovation/refactor/150
rlajm1203 Jan 16, 2025
a446d2d
Merge branch 'develop' into feat/119
rlajm1203 Jan 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.whoz_in.domain.device;

import com.whoz_in.domain.device.model.Device;
import java.util.List;
import com.whoz_in.domain.device.model.DeviceId;
import java.util.Optional;

public interface DeviceRepository {
void save(Device device);
List<Device> findAll();

//해당 mac을 포함하는 device를 찾는 메서드
Optional<Device> findByMac(String mac);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static AccountType findAccountType(String accountType){
return Arrays.stream(AccountType.values())
.filter(at -> at.name().equals(accountType))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("no account type"));
.orElseThrow(() -> new IllegalStateException("no account type"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public static SocialProvider findSocialProvider(String socialProvider){
return Arrays.stream(SocialProvider.values())
.filter(provider -> provider.getProviderName().equals(socialProvider))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("no social provider"));
.orElseThrow(() -> new IllegalStateException("no social provider"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

public interface MonitorLogRepository {
void save(MonitorLog log);
void saveAll(Collection<MonitorLog> logs);
List<MonitorLog> findAll();
List<MonitorLog> findByUpdatedAtAfterOrderByUpdatedAtDesc(LocalDateTime updatedAt); // 해당 시간 이후의 로그를 가져오기
// TODO: 이전 로그까지 가져와야 할까?
boolean existsAfter(String mac, LocalDateTime time);
default void mustExistAfter(String mac, LocalDateTime time){
if (!existsAfter(mac, time))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public static class DataSourceProperties {
@Getter
@Setter
public static class HibernateProperties {
private String ddlAuto;
private String physicalNamingStrategy;
private boolean formatSql;
private boolean showSql;
}
Expand Down Expand Up @@ -80,7 +82,9 @@ public LocalContainerEntityManagerFactoryBean apiQueryJpaEntityManagerFactory(
.properties(
Map.of(
"hibernate.show_sql", hibernateProperties.showSql,
"hibernate.format_sql", hibernateProperties.formatSql
"hibernate.format_sql", hibernateProperties.formatSql,
"hibernate.hbm2ddl.auto", hibernateProperties.ddlAuto,
"hibernate.physical_naming_strategy", hibernateProperties.physicalNamingStrategy
)
)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.whoz_in.api_query_jpa.device;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ActiveDeviceEntity {

@Id
private UUID deviceId;

@Column(nullable = false)
private LocalDateTime connectedTime;

private LocalDateTime disConnectedTime;

private Duration totalActiveTime;

private boolean isActive;

private ActiveDeviceEntity(UUID deviceId, LocalDateTime connectedTime) {
this.deviceId = deviceId;
this.connectedTime = connectedTime;
this.isActive = true;
}

public void activeOn(LocalDateTime connectedTime){
this.isActive = true;
this.connectedTime = connectedTime;
this.disConnectedTime = null;
}

public void inActiveOn(LocalDateTime disConnectedTime){
this.isActive = false;
this.disConnectedTime = disConnectedTime;
addTotalActiveTime();
}

private void addTotalActiveTime(){
Duration add = Duration.between(connectedTime, disConnectedTime).abs();
this.totalActiveTime = Objects.nonNull(totalActiveTime) ? totalActiveTime.plus(add) : add;
}

public static ActiveDeviceEntity create(UUID deviceId, LocalDateTime connectedTime){
return new ActiveDeviceEntity(deviceId, connectedTime);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.whoz_in.api_query_jpa.device;

import com.whoz_in.api_query_jpa.member.Member;
import com.whoz_in.api_query_jpa.member.MemberRepository;
import com.whoz_in.main_api.query.device.application.active.ActiveDevice;
import com.whoz_in.main_api.query.device.application.active.ActiveDeviceViewer;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class ActiveDeviceJpaViewer implements ActiveDeviceViewer {

private final ActiveDeviceRepository activeDeviceRepository;
private final DeviceRepository deviceRepository;
private final MemberRepository memberRepository;

@Override
public Optional<ActiveDevice> findByDeviceId(String deviceId) {
ActiveDeviceEntity activeDevice = activeDeviceRepository.findByDeviceId(UUID.fromString(deviceId)).orElse(null);
Member member = memberRepository.findByDeviceId(UUID.fromString(deviceId)).orElse(null);

if(member == null || activeDevice == null) return Optional.empty();

return createOptionalActiveDevice(activeDevice, member);
}

@Override
public List<ActiveDevice> findAll() {
List<ActiveDeviceEntity> entities = activeDeviceRepository.findAll();
List<UUID> deviceIds = entities.stream().map(ActiveDeviceEntity::getDeviceId).toList();
List<Device> devices = deviceRepository.findAll();
List<Member> members = memberRepository.findByDeviceIds(deviceIds);

return entities.stream()
.map(entity-> {
Device device = devices.stream().filter(d -> d.getId().equals(entity.getDeviceId())).findFirst().orElse(null);
if(device == null) return null;
Member member = members.stream().filter(m -> m.getId().equals(device.getMemberId())).findFirst().orElse(null);
if (member == null) return null;
return createOptionalActiveDevice(entity, member).orElse(null);
})
.filter(Objects::nonNull)
.toList();
}

private Optional<ActiveDevice> createOptionalActiveDevice(ActiveDeviceEntity entity, Member member){
return Optional.of(new ActiveDevice(
entity.getDeviceId(),
member.getId(),
entity.getConnectedTime(),
entity.getDisConnectedTime(),
entity.getTotalActiveTime(),
entity.isActive()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.whoz_in.api_query_jpa.device;

import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ActiveDeviceRepository extends JpaRepository<ActiveDeviceEntity, UUID> {

Optional<ActiveDeviceEntity> findByDeviceId(UUID deviceId);

void deleteByDeviceId(UUID deviceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 코드 패치에 대한 간단한 코드 리뷰는 다음과 같습니다:

  1. 이 코드는 jakarta.persistence.JoinColumn을 가져오는 데 세미콜론이 누락되어 있어서 코드가 완전하지 않았습니다. 이 패치는 이 문제를 해결합니다.

  2. 개선 제안은 없습니다. 이는 이전 코드에 문제가 있었고, 이 패치가 그 문제를 정확하게 해결했기 때문입니다.

  3. 에러가 나는 요소가 있었지만, 수정 된 코드에서는 파악되지 않습니다.

  4. 이 코드를 통합하면 이전 버전의 오류가 해결될 것입니다.

그러나 이 코드의 기능 및 행동이 올바르게 작동하는지 확인하려면 전체 프로젝트나 이 코드 패치가 적용되는 다른 코드 부분을 보고 이해하거나, 이 변경 사항에 대한 테스트 케이스가 필요합니다. 이 패치가 별도의 기능을 수정하는 경우, 해당 기능은 단위 테스트를 통해 완전히 테스트되어야 합니다.

import java.util.List;
Expand Down Expand Up @@ -33,4 +33,4 @@ public class Device {
@JoinColumn(name = "device_id", referencedColumnName = "id")
private List<DeviceInfo> deviceInfos;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
import java.util.List;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface DeviceRepository extends JpaRepository<Device, UUID> {

@Query(nativeQuery = true,
value = "SELECT id , member_id FROM device_entity")
List<Device> findAll();

public interface DeviceRepository extends JpaRepository<Device, Long> {
List<Device> findAllByMemberId(UUID ownerId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.whoz_in.api_query_jpa.device;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

@Repository
@Slf4j
public class InMemoryActiveDeviceRepository {

private final Map<UUID, ActiveDeviceEntity> repository;

public InMemoryActiveDeviceRepository(){
this.repository = new ConcurrentHashMap<>();
}

public UUID save(ActiveDeviceEntity device){
UUID id = device.getDeviceId();
repository.put(id, device); // 갱신된 데이터가 삽입될 수 있도록
return device.getDeviceId();
}

public void saveAll(List<ActiveDeviceEntity> devices){
devices.forEach(this::save);
}

public List<ActiveDeviceEntity> findAll(){
return repository.values().stream().toList();
}

public Optional<ActiveDeviceEntity> findByDeviceId(UUID deviceId){
if(repository.containsKey(deviceId))
return Optional.of(repository.get(deviceId));
return Optional.empty();
}

public void deleteById(UUID deviceId){
repository.remove(deviceId);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.whoz_in.api_query_jpa.device.event;

import com.whoz_in.api_query_jpa.device.ActiveDeviceEntity;
import com.whoz_in.api_query_jpa.device.ActiveDeviceRepository;
import com.whoz_in.api_query_jpa.device.InMemoryActiveDeviceRepository;
import com.whoz_in.main_api.query.device.application.active.event.ActiveDeviceFinded;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Component
@RequiredArgsConstructor
@Slf4j
public class ActiveDeviceEventHandler {

private final ActiveDeviceRepository activeDeviceRepository;

@Transactional(isolation = Isolation.SERIALIZABLE)
@EventListener(ActiveDeviceFinded.class)
public void saveActiveDevices(ActiveDeviceFinded event) {
List<UUID> deviceIds = event.getDevices();
List<ActiveDeviceEntity> activeDeviceEntities = activeDeviceRepository.findAll();

List<UUID> deviceIdFromDB = activeDeviceEntities.stream().map(ActiveDeviceEntity::getDeviceId).toList();

List<ActiveDeviceEntity> firstActiveDevices = deviceIds.stream()
.filter(deviceId -> deviceIdFromDB.stream().noneMatch(idFromDB -> idFromDB.equals(deviceId)))
.map(deviceId -> ActiveDeviceEntity.create(deviceId, LocalDateTime.now())) // TODO: active Time 을 이 시점으로 설정해도 될까?
.toList();


List<ActiveDeviceEntity> nonFirstActiveDevice = deviceIds.stream()
.filter(deviceId -> deviceIdFromDB.stream().anyMatch(idFromDB -> idFromDB.equals(deviceId)))
.map(deviceId -> {
return activeDeviceEntities.stream()
.filter(active -> active.getDeviceId().equals(deviceId))
.findAny()
.orElse(null);
})
.filter(Objects::nonNull)
.toList();


saveFirstActive(firstActiveDevices);
saveNonFirstActive(nonFirstActiveDevice);
}

private void saveFirstActive(List<ActiveDeviceEntity> entities){
// 처음으로 Active 된 Device 는 그냥 저장 가능
activeDeviceRepository.saveAll(entities);
}

private void saveNonFirstActive(List<ActiveDeviceEntity> entities){
// 참조를 이용한 JPA 변경 감지 짝퉁
entities.forEach(activeDevice -> {
if(!activeDevice.isActive()) activeDevice.activeOn(LocalDateTime.now());
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.whoz_in.api_query_jpa.device.event;

import com.whoz_in.api_query_jpa.device.ActiveDeviceEntity;
import com.whoz_in.api_query_jpa.device.ActiveDeviceRepository;
import com.whoz_in.api_query_jpa.device.InMemoryActiveDeviceRepository;
import com.whoz_in.main_api.query.device.application.active.event.InActiveDeviceFinded;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Component
@RequiredArgsConstructor
public class InActiveDeviceEventHandler {

private final ActiveDeviceRepository activeDeviceRepository;

// ActiveDeviceEvent 핸들러에서 데이터를 수정할 수 있으므로 격리 수준을 serializable 로 설정
@Transactional(isolation = Isolation.SERIALIZABLE)
@EventListener(InActiveDeviceFinded.class)
public void processInActiveDevices(InActiveDeviceFinded event) {
// InActiveDevice 찾는 로직
List<UUID> devices = event.getDevices();
List<ActiveDeviceEntity> entities = activeDeviceRepository.findAll();

entities.stream()
.filter(activeDevice -> devices.stream()
.anyMatch(device -> device.equals(activeDevice.getDeviceId())))
.forEach(activeDevice -> activeDevice.inActiveOn(LocalDateTime.now()));
}

}
Loading
Loading