From c501bd77d8b19c80f8cfbdac011ece6c415435d4 Mon Sep 17 00:00:00 2001 From: redjungi Date: Tue, 14 Apr 2026 20:52:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=EC=86=8C=EC=BC=93=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EB=B8=8C=EB=A1=9C=EB=93=9C=EC=BA=90=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=A7=80=EC=9B=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../realtime/socketio/SocketIoBroadcastAdapter.java | 9 +++++++++ .../realtime/port/out/BroadcastRefetchPort.java | 1 + .../realtime/service/RefetchEventListener.java | 6 +++++- .../realtime/service/RefetchEventPublisher.java | 7 +++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/process/clash/adapter/realtime/socketio/SocketIoBroadcastAdapter.java b/src/main/java/com/process/clash/adapter/realtime/socketio/SocketIoBroadcastAdapter.java index 11361efa4..496ee89b4 100644 --- a/src/main/java/com/process/clash/adapter/realtime/socketio/SocketIoBroadcastAdapter.java +++ b/src/main/java/com/process/clash/adapter/realtime/socketio/SocketIoBroadcastAdapter.java @@ -32,4 +32,13 @@ public void broadcastRefetchToUsers(RefetchNotice notice, Collection userI operations.sendEvent(EVENT_CHANGE, payload); } } + + @Override + public void broadcastRefetchToAll(RefetchNotice notice) { + if (notice == null) { + return; + } + ChangePayload payload = ChangePayload.from(notice); + socketIOServer.getBroadcastOperations().sendEvent(EVENT_CHANGE, payload); + } } diff --git a/src/main/java/com/process/clash/application/realtime/port/out/BroadcastRefetchPort.java b/src/main/java/com/process/clash/application/realtime/port/out/BroadcastRefetchPort.java index bddad8e84..4e2b5b225 100644 --- a/src/main/java/com/process/clash/application/realtime/port/out/BroadcastRefetchPort.java +++ b/src/main/java/com/process/clash/application/realtime/port/out/BroadcastRefetchPort.java @@ -5,4 +5,5 @@ public interface BroadcastRefetchPort { void broadcastRefetchToUsers(RefetchNotice notice, Collection userIds); + void broadcastRefetchToAll(RefetchNotice notice); } diff --git a/src/main/java/com/process/clash/application/realtime/service/RefetchEventListener.java b/src/main/java/com/process/clash/application/realtime/service/RefetchEventListener.java index 6da92c8f3..77f913796 100644 --- a/src/main/java/com/process/clash/application/realtime/service/RefetchEventListener.java +++ b/src/main/java/com/process/clash/application/realtime/service/RefetchEventListener.java @@ -16,10 +16,14 @@ public class RefetchEventListener { @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true) public void onRefetchEvent(RefetchEvent event) { - if (event == null || event.notice() == null || event.userIds() == null) { + if (event == null || event.notice() == null) { return; } Collection userIds = event.userIds(); + if (userIds == null) { + broadcastRefetchPort.broadcastRefetchToAll(event.notice()); + return; + } if (userIds.isEmpty()) { return; } diff --git a/src/main/java/com/process/clash/application/realtime/service/RefetchEventPublisher.java b/src/main/java/com/process/clash/application/realtime/service/RefetchEventPublisher.java index d39dc2507..b71da7b27 100644 --- a/src/main/java/com/process/clash/application/realtime/service/RefetchEventPublisher.java +++ b/src/main/java/com/process/clash/application/realtime/service/RefetchEventPublisher.java @@ -30,4 +30,11 @@ public void publish(RefetchNotice notice, Collection userIds) { } applicationEventPublisher.publishEvent(new RefetchEvent(notice, deduped)); } + + public void publishToAll(RefetchNotice notice) { + if (notice == null) { + return; + } + applicationEventPublisher.publishEvent(new RefetchEvent(notice, null)); + } } From 36da08dfb89120754db4ce70a1ca9af59d741122 Mon Sep 17 00:00:00 2001 From: redjungi Date: Tue, 14 Apr 2026 20:52:35 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=EB=A1=9D/=EC=88=98=EC=A0=95/=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20=EC=86=8C=EC=BC=93=20=EB=B8=8C=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=EC=BA=90=EC=8A=A4=ED=8A=B8=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CreateAnnouncementAdminService.java | 3 +++ .../DeleteAnnouncementAdminService.java | 3 +++ .../UpdateAnnouncementAdminService.java | 3 +++ .../realtime/AnnouncementRefetchNotifier.java | 19 +++++++++++++++++++ .../CreateAnnouncementAdminServiceTest.java | 6 +++++- .../DeleteAnnouncementAdminServiceTest.java | 6 +++++- .../UpdateAnnouncementAdminServiceTest.java | 6 +++++- 7 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/process/clash/application/announcement/realtime/AnnouncementRefetchNotifier.java diff --git a/src/main/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminService.java b/src/main/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminService.java index f818f6573..3cfdcb167 100644 --- a/src/main/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminService.java +++ b/src/main/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminService.java @@ -3,6 +3,7 @@ import com.process.clash.application.announcement.admin.data.CreateAnnouncementAdminData; import com.process.clash.application.announcement.admin.port.in.CreateAnnouncementAdminUseCase; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.policy.CheckAdminPolicy; import com.process.clash.domain.announcement.entity.Announcement; import lombok.RequiredArgsConstructor; @@ -16,12 +17,14 @@ public class CreateAnnouncementAdminService implements CreateAnnouncementAdminUs private final AnnouncementRepositoryPort announcementRepositoryPort; private final CheckAdminPolicy checkAdminPolicy; + private final AnnouncementRefetchNotifier announcementRefetchNotifier; @Override public CreateAnnouncementAdminData.Result execute(CreateAnnouncementAdminData.Command command) { checkAdminPolicy.check(command.actor()); Announcement saved = announcementRepositoryPort.save(command.toDomain()); + announcementRefetchNotifier.notifyAnnouncementChanged(); return CreateAnnouncementAdminData.Result.from(saved); } } diff --git a/src/main/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminService.java b/src/main/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminService.java index 88ba466fd..4786d4288 100644 --- a/src/main/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminService.java +++ b/src/main/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminService.java @@ -4,6 +4,7 @@ import com.process.clash.application.announcement.admin.port.in.DeleteAnnouncementAdminUseCase; import com.process.clash.application.announcement.exception.exception.notfound.AnnouncementNotFoundException; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.policy.CheckAdminPolicy; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,6 +17,7 @@ public class DeleteAnnouncementAdminService implements DeleteAnnouncementAdminUs private final AnnouncementRepositoryPort announcementRepositoryPort; private final CheckAdminPolicy checkAdminPolicy; + private final AnnouncementRefetchNotifier announcementRefetchNotifier; @Override public void execute(DeleteAnnouncementAdminData.Command command) { @@ -26,5 +28,6 @@ public void execute(DeleteAnnouncementAdminData.Command command) { } announcementRepositoryPort.deleteById(command.id()); + announcementRefetchNotifier.notifyAnnouncementChanged(); } } diff --git a/src/main/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminService.java b/src/main/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminService.java index 7d8e65129..781f1e6e5 100644 --- a/src/main/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminService.java +++ b/src/main/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminService.java @@ -4,6 +4,7 @@ import com.process.clash.application.announcement.admin.port.in.UpdateAnnouncementAdminUseCase; import com.process.clash.application.announcement.exception.exception.notfound.AnnouncementNotFoundException; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.policy.CheckAdminPolicy; import com.process.clash.domain.announcement.entity.Announcement; import lombok.RequiredArgsConstructor; @@ -17,6 +18,7 @@ public class UpdateAnnouncementAdminService implements UpdateAnnouncementAdminUs private final AnnouncementRepositoryPort announcementRepositoryPort; private final CheckAdminPolicy checkAdminPolicy; + private final AnnouncementRefetchNotifier announcementRefetchNotifier; @Override public UpdateAnnouncementAdminData.Result execute(UpdateAnnouncementAdminData.Command command) { @@ -38,6 +40,7 @@ public UpdateAnnouncementAdminData.Result execute(UpdateAnnouncementAdminData.Co ); Announcement saved = announcementRepositoryPort.save(updated); + announcementRefetchNotifier.notifyAnnouncementChanged(); return UpdateAnnouncementAdminData.Result.from(saved); } } diff --git a/src/main/java/com/process/clash/application/announcement/realtime/AnnouncementRefetchNotifier.java b/src/main/java/com/process/clash/application/announcement/realtime/AnnouncementRefetchNotifier.java new file mode 100644 index 000000000..8340517e3 --- /dev/null +++ b/src/main/java/com/process/clash/application/announcement/realtime/AnnouncementRefetchNotifier.java @@ -0,0 +1,19 @@ +package com.process.clash.application.announcement.realtime; + +import com.process.clash.application.realtime.data.ChangeDomain; +import com.process.clash.application.realtime.data.ChangeType; +import com.process.clash.application.realtime.data.RefetchNotice; +import com.process.clash.application.realtime.service.RefetchEventPublisher; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AnnouncementRefetchNotifier { + + private final RefetchEventPublisher refetchEventPublisher; + + public void notifyAnnouncementChanged() { + refetchEventPublisher.publishToAll(RefetchNotice.of(ChangeDomain.ANNOUNCEMENT, ChangeType.DATA_CHANGED)); + } +} diff --git a/src/test/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminServiceTest.java b/src/test/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminServiceTest.java index 152dcc5ac..9b38259f3 100644 --- a/src/test/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminServiceTest.java +++ b/src/test/java/com/process/clash/application/announcement/admin/service/CreateAnnouncementAdminServiceTest.java @@ -2,6 +2,7 @@ import com.process.clash.application.announcement.admin.data.CreateAnnouncementAdminData; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.actor.Actor; import com.process.clash.application.common.policy.CheckAdminPolicy; import com.process.clash.application.user.user.exception.exception.forbidden.RequiredAdminRoleException; @@ -30,11 +31,14 @@ class CreateAnnouncementAdminServiceTest { @Mock private CheckAdminPolicy checkAdminPolicy; + @Mock + private AnnouncementRefetchNotifier announcementRefetchNotifier; + private CreateAnnouncementAdminService service; @BeforeEach void setUp() { - service = new CreateAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy); + service = new CreateAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy, announcementRefetchNotifier); } @Test diff --git a/src/test/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminServiceTest.java b/src/test/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminServiceTest.java index 23dc50385..69d69922f 100644 --- a/src/test/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminServiceTest.java +++ b/src/test/java/com/process/clash/application/announcement/admin/service/DeleteAnnouncementAdminServiceTest.java @@ -3,6 +3,7 @@ import com.process.clash.application.announcement.admin.data.DeleteAnnouncementAdminData; import com.process.clash.application.announcement.exception.exception.notfound.AnnouncementNotFoundException; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.actor.Actor; import com.process.clash.application.common.policy.CheckAdminPolicy; import com.process.clash.application.user.user.exception.exception.forbidden.RequiredAdminRoleException; @@ -30,11 +31,14 @@ class DeleteAnnouncementAdminServiceTest { @Mock private CheckAdminPolicy checkAdminPolicy; + @Mock + private AnnouncementRefetchNotifier announcementRefetchNotifier; + private DeleteAnnouncementAdminService service; @BeforeEach void setUp() { - service = new DeleteAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy); + service = new DeleteAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy, announcementRefetchNotifier); } @Test diff --git a/src/test/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminServiceTest.java b/src/test/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminServiceTest.java index 4df81d376..97709b408 100644 --- a/src/test/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminServiceTest.java +++ b/src/test/java/com/process/clash/application/announcement/admin/service/UpdateAnnouncementAdminServiceTest.java @@ -3,6 +3,7 @@ import com.process.clash.application.announcement.admin.data.UpdateAnnouncementAdminData; import com.process.clash.application.announcement.exception.exception.notfound.AnnouncementNotFoundException; import com.process.clash.application.announcement.port.out.AnnouncementRepositoryPort; +import com.process.clash.application.announcement.realtime.AnnouncementRefetchNotifier; import com.process.clash.application.common.policy.CheckAdminPolicy; import com.process.clash.application.user.user.exception.exception.forbidden.RequiredAdminRoleException; import com.process.clash.domain.announcement.entity.Announcement; @@ -32,11 +33,14 @@ class UpdateAnnouncementAdminServiceTest { @Mock private CheckAdminPolicy checkAdminPolicy; + @Mock + private AnnouncementRefetchNotifier announcementRefetchNotifier; + private UpdateAnnouncementAdminService service; @BeforeEach void setUp() { - service = new UpdateAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy); + service = new UpdateAnnouncementAdminService(announcementRepositoryPort, checkAdminPolicy, announcementRefetchNotifier); } @Test From a116e3355103b01c051b9ee12b3c467eab98eeae Mon Sep 17 00:00:00 2001 From: redjungi Date: Wed, 15 Apr 2026 14:54:21 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20ChangeDomain=EC=97=90=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=EB=90=9C=20ANNOUNCEMENT=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../process/clash/application/realtime/data/ChangeDomain.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/process/clash/application/realtime/data/ChangeDomain.java b/src/main/java/com/process/clash/application/realtime/data/ChangeDomain.java index c78da6f79..b8947e9a0 100644 --- a/src/main/java/com/process/clash/application/realtime/data/ChangeDomain.java +++ b/src/main/java/com/process/clash/application/realtime/data/ChangeDomain.java @@ -5,5 +5,6 @@ public enum ChangeDomain { COMPETE, USER, RECORD, - ATTENDANCE + ATTENDANCE, + ANNOUNCEMENT }