diff --git a/Makefile b/Makefile
index c312ce16..4855cd12 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
all: build
start:
- @docker-compose -f docker-compose.ci.yml up -d
+ @docker compose -f docker-compose.ci.yml up -d
build:
@./gradlew build --warning-mode all
diff --git a/apps/main/resources/application.properties b/apps/main/resources/application.properties
new file mode 100644
index 00000000..e439ebd8
--- /dev/null
+++ b/apps/main/resources/application.properties
@@ -0,0 +1 @@
+spring.main.allow-bean-definition-overriding=true
diff --git a/apps/main/resources/backoffice_frontend/templates/pages/courses/partials/list_courses.ftl b/apps/main/resources/backoffice_frontend/templates/pages/courses/partials/list_courses.ftl
index e81af3c3..aa64bee9 100644
--- a/apps/main/resources/backoffice_frontend/templates/pages/courses/partials/list_courses.ftl
+++ b/apps/main/resources/backoffice_frontend/templates/pages/courses/partials/list_courses.ftl
@@ -142,12 +142,12 @@
const urlParts = inputs.map(input => input.name + "=" + input.value);
- const url = "http://localhost:8091/courses?" + urlParts.join("&");
+ const url = "http://localhost:8040/courses?" + urlParts.join("&");
addCoursesList(url);
}
diff --git a/apps/main/tv/codely/apps/backoffice/backend/BackofficeBackendApplication.java b/apps/main/tv/codely/apps/backoffice/backend/BackofficeBackendApplication.java
index 873122f3..0a9374e3 100644
--- a/apps/main/tv/codely/apps/backoffice/backend/BackofficeBackendApplication.java
+++ b/apps/main/tv/codely/apps/backoffice/backend/BackofficeBackendApplication.java
@@ -7,6 +7,7 @@
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
+import tv.codely.apps.backoffice.backend.command.ConsumeRabbitMqDomainEventsCommand;
import tv.codely.shared.domain.Service;
@SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
@@ -17,8 +18,10 @@
public class BackofficeBackendApplication {
public static HashMap> commands() {
- return new HashMap>() {
- {}
+ return new HashMap<>() {
+ {
+ put("domain-events:rabbitmq:consume", ConsumeRabbitMqDomainEventsCommand.class);
+ }
};
}
}
diff --git a/apps/main/tv/codely/apps/backoffice/backend/command/.gitkeep b/apps/main/tv/codely/apps/backoffice/backend/command/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/apps/main/tv/codely/apps/backoffice/backend/command/ConsumeRabbitMqDomainEventsCommand.java b/apps/main/tv/codely/apps/backoffice/backend/command/ConsumeRabbitMqDomainEventsCommand.java
new file mode 100644
index 00000000..018972f4
--- /dev/null
+++ b/apps/main/tv/codely/apps/backoffice/backend/command/ConsumeRabbitMqDomainEventsCommand.java
@@ -0,0 +1,18 @@
+package tv.codely.apps.backoffice.backend.command;
+
+import tv.codely.shared.infrastructure.bus.event.rabbitmq.RabbitMqDomainEventsConsumer;
+import tv.codely.shared.infrastructure.cli.ConsoleCommand;
+
+public final class ConsumeRabbitMqDomainEventsCommand extends ConsoleCommand {
+
+ private final RabbitMqDomainEventsConsumer consumer;
+
+ public ConsumeRabbitMqDomainEventsCommand(RabbitMqDomainEventsConsumer consumer) {
+ this.consumer = consumer;
+ }
+
+ @Override
+ public void execute(String[] args) {
+ consumer.consume("backoffice");
+ }
+}
diff --git a/apps/main/tv/codely/apps/backoffice/frontend/config/BackofficeFrontendWebConfig.java b/apps/main/tv/codely/apps/backoffice/frontend/config/BackofficeFrontendWebConfig.java
index 31405d6f..62749d15 100644
--- a/apps/main/tv/codely/apps/backoffice/frontend/config/BackofficeFrontendWebConfig.java
+++ b/apps/main/tv/codely/apps/backoffice/frontend/config/BackofficeFrontendWebConfig.java
@@ -1,7 +1,9 @@
package tv.codely.apps.backoffice.frontend.config;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
@@ -10,6 +12,10 @@
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
+import tv.codely.shared.infrastructure.bus.event.mysql.MySqlEventBus;
+import tv.codely.shared.infrastructure.bus.event.rabbitmq.RabbitMqEventBus;
+import tv.codely.shared.infrastructure.bus.event.rabbitmq.RabbitMqPublisher;
+
@Configuration
@EnableWebMvc
public class BackofficeFrontendWebConfig implements WebMvcConfigurer {
@@ -43,4 +49,13 @@ public FreeMarkerConfigurer freeMarkerConfigurer() {
return configurer;
}
+
+ @Primary
+ @Bean
+ public RabbitMqEventBus rabbitMqEventBus(
+ RabbitMqPublisher publisher,
+ @Qualifier("backofficeMysqlEventBus") MySqlEventBus failoverPublisher
+ ) {
+ return new RabbitMqEventBus(publisher, failoverPublisher);
+ }
}
diff --git a/apps/main/tv/codely/apps/mooc/backend/command/ConsumeRabbitMqDomainEventsCommand.java b/apps/main/tv/codely/apps/mooc/backend/command/ConsumeRabbitMqDomainEventsCommand.java
index 993dcd5b..ce5d7bdc 100644
--- a/apps/main/tv/codely/apps/mooc/backend/command/ConsumeRabbitMqDomainEventsCommand.java
+++ b/apps/main/tv/codely/apps/mooc/backend/command/ConsumeRabbitMqDomainEventsCommand.java
@@ -13,6 +13,6 @@ public ConsumeRabbitMqDomainEventsCommand(RabbitMqDomainEventsConsumer consumer)
@Override
public void execute(String[] args) {
- consumer.consume();
+ consumer.consume("mooc");
}
}
diff --git a/apps/main/tv/codely/apps/mooc/backend/config/MoocBackendServerConfiguration.java b/apps/main/tv/codely/apps/mooc/backend/config/MoocBackendServerConfiguration.java
index 9974cddc..3041e7bd 100644
--- a/apps/main/tv/codely/apps/mooc/backend/config/MoocBackendServerConfiguration.java
+++ b/apps/main/tv/codely/apps/mooc/backend/config/MoocBackendServerConfiguration.java
@@ -1,5 +1,7 @@
package tv.codely.apps.mooc.backend.config;
+import java.util.Optional;
+
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -10,9 +12,9 @@
@Configuration
public class MoocBackendServerConfiguration {
- private final RequestMappingHandlerMapping mapping;
+ private final Optional mapping;
- public MoocBackendServerConfiguration(RequestMappingHandlerMapping mapping) {
+ public MoocBackendServerConfiguration(Optional mapping) {
this.mapping = mapping;
}
@@ -20,7 +22,7 @@ public MoocBackendServerConfiguration(RequestMappingHandlerMapping mapping) {
public FilterRegistrationBean apiExceptionMiddleware() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new ApiExceptionMiddleware(mapping));
+ mapping.ifPresent(map -> registrationBean.setFilter(new ApiExceptionMiddleware(map)));
return registrationBean;
}
diff --git a/apps/main/tv/codely/apps/mooc/backend/controller/playground/DomainEventPostController.java b/apps/main/tv/codely/apps/mooc/backend/controller/playground/DomainEventPostController.java
new file mode 100644
index 00000000..dfc96572
--- /dev/null
+++ b/apps/main/tv/codely/apps/mooc/backend/controller/playground/DomainEventPostController.java
@@ -0,0 +1,53 @@
+package tv.codely.apps.mooc.backend.controller.playground;
+
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessagePropertiesBuilder;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import tv.codely.shared.domain.Utils;
+
+@RestController
+record DomainEventPostController(RabbitTemplate rabbitTemplate) {
+ @PostMapping(value = "/domain-events")
+ public ResponseEntity index(@RequestBody Request request) {
+ System.out.println(request.eventName());
+
+ var serializedEvent = Utils.jsonEncode(request.eventRaw());
+
+ Message message = new Message(
+ serializedEvent.getBytes(),
+ MessagePropertiesBuilder.newInstance().setContentEncoding("utf-8").setContentType("application/json").build()
+ );
+
+ rabbitTemplate.send("domain_events", request.eventName(), message);
+
+ return new ResponseEntity<>(HttpStatus.CREATED);
+ }
+}
+
+final class Request {
+
+ private String eventName;
+ private Object eventRaw;
+
+ public void setEventName(String eventName) {
+ this.eventName = eventName;
+ }
+
+ public void setEventRaw(Object eventRaw) {
+ this.eventRaw = eventRaw;
+ }
+
+ String eventName() {
+ return eventName;
+ }
+
+ Object eventRaw() {
+ return eventRaw;
+ }
+}
diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml
index 654ffd12..d2c1c99c 100755
--- a/docker-compose.ci.yml
+++ b/docker-compose.ci.yml
@@ -23,7 +23,7 @@ services:
platform: linux/amd64
restart: unless-stopped
ports:
- - "5630:5672"
+ - "5672:5672"
- "8090:15672"
environment:
- RABBITMQ_DEFAULT_USER=codely
diff --git a/docker-compose.yml b/docker-compose.yml
index 3da6fcb7..216bacd5 100755
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -23,7 +23,7 @@ services:
platform: linux/amd64
restart: unless-stopped
ports:
- - "5630:5672"
+ - "5672:5672"
- "8090:15672"
environment:
- RABBITMQ_DEFAULT_USER=codely
@@ -51,12 +51,29 @@ services:
volumes:
- .:/app:delegated
- backoffice_backend_gradle_cache:/app/.gradle
+ - backoffice_backend_build:/app/build
depends_on:
- shared_mysql
- shared_rabbitmq
- backoffice_elasticsearch
command: ["./gradlew", "bootRun", "--args", "backoffice_backend server"]
+ backoffice_backend_consumers_java:
+ container_name: codely-java_ddd_example-backoffice_backend_consumers
+ build:
+ context: .
+ dockerfile: Dockerfile
+ restart: unless-stopped
+ volumes:
+ - .:/app:delegated
+ - backoffice_consumers_gradle_cache:/app/.gradle
+ - backoffice_consumers_build:/app/build
+ depends_on:
+ - shared_mysql
+ - shared_rabbitmq
+ - backoffice_elasticsearch
+ command: ["./gradlew", "bootRun", "--args", "backoffice_backend domain-events:rabbitmq:consume"]
+
backoffice_frontend_server_java:
container_name: codely-java_ddd_example-backoffice_frontend_server
build:
@@ -68,6 +85,7 @@ services:
volumes:
- .:/app:delegated
- backoffice_frontend_gradle_cache:/app/.gradle
+ - backoffice_frontend_build:/app/build
depends_on:
- shared_mysql
- shared_rabbitmq
@@ -85,29 +103,37 @@ services:
volumes:
- .:/app:delegated
- mooc_backend_gradle_cache:/app/.gradle
+ - mooc_backend_build:/app/build
depends_on:
- shared_mysql
- shared_rabbitmq
- backoffice_elasticsearch
command: ["./gradlew", "bootRun", "--args", "mooc_backend server"]
- test_server_java:
- container_name: codely-java_ddd_example-test_server
+ mooc_backend_consumers_java:
+ container_name: codely-java_ddd_example-mooc_backend_consumers
build:
context: .
dockerfile: Dockerfile
restart: unless-stopped
volumes:
- .:/app:delegated
- - test_gradle_cache:/app/.gradle
+ - mooc_consumers_gradle_cache:/app/.gradle
+ - mooc_consumers_build:/app/build
depends_on:
- shared_mysql
- shared_rabbitmq
- backoffice_elasticsearch
- tty: true
+ command: ["./gradlew", "bootRun", "--args", "mooc_backend domain-events:rabbitmq:consume"]
volumes:
backoffice_backend_gradle_cache:
+ backoffice_backend_build:
+ backoffice_consumers_gradle_cache:
+ backoffice_consumers_build:
backoffice_frontend_gradle_cache:
+ backoffice_frontend_build:
mooc_backend_gradle_cache:
- test_gradle_cache:
+ mooc_backend_build:
+ mooc_consumers_gradle_cache:
+ mooc_consumers_build:
diff --git a/doc/endpoints/backoffice_frontend.http b/etc/http/backoffice_frontend.http
similarity index 100%
rename from doc/endpoints/backoffice_frontend.http
rename to etc/http/backoffice_frontend.http
diff --git a/etc/http/publish_domain_events.http b/etc/http/publish_domain_events.http
new file mode 100644
index 00000000..309c2fd7
--- /dev/null
+++ b/etc/http/publish_domain_events.http
@@ -0,0 +1,62 @@
+POST http://localhost:8030/domain-events
+Content-Type: application/json
+
+{
+ "eventName": "course.created",
+ "eventRaw": {
+ "data": {
+ "id": "{{$random.uuid}}",
+ "type": "course.created",
+ "occurred_on": "2023-11-14 10:00:00",
+ "attributes": {
+ "id": "c3a11f1d-512e-420b-aeae-e687a3c449aa",
+ "name": "Demo course",
+ "duration": "2 days"
+ }
+ },
+ "meta": {
+ }
+ }
+}
+
+###
+POST http://localhost:8030/domain-events
+Content-Type: application/json
+
+{
+ "eventName": "course.renamed",
+ "eventRaw": {
+ "data": {
+ "id": "{{$random.uuid}}",
+ "type": "course.renamed",
+ "occurred_on": "2023-11-14 10:00:00",
+ "attributes": {
+ "id": "7b081a3e-f90e-4efe-a3a5-81e853e89c8b",
+ "name": "Este es el nombre bueno"
+ }
+ },
+ "meta": {
+ }
+ }
+}
+
+###
+POST http://localhost:8030/domain-events
+Content-Type: application/json
+
+{
+ "eventName": "course.renamed",
+ "eventRaw": {
+ "data": {
+ "id": "{{$random.uuid}}",
+ "type": "course.renamed",
+ "occurred_on": "2022-11-14 10:00:00",
+ "attributes": {
+ "id": "7b081a3e-f90e-4efe-a3a5-81e853e89c8b",
+ "name": "Este es el nombre malo"
+ }
+ },
+ "meta": {
+ }
+ }
+}
diff --git a/etc/scripts/create_infinite_courses.sh b/etc/scripts/create_infinite_courses.sh
new file mode 100644
index 00000000..2467ee9a
--- /dev/null
+++ b/etc/scripts/create_infinite_courses.sh
@@ -0,0 +1,33 @@
+function create_course() {
+ eventId=$(uuidgen)
+ courseId=$(uuidgen)
+ courseName=$(shuf -n3 /usr/share/dict/words | xargs)
+ courseDuration=$((1 + RANDOM % 1000))
+
+ curl -X POST --location "http://localhost:8030/domain-events" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "eventName": "course.created",
+ "eventRaw": {
+ "data": {
+ "id": "'"$eventId"'",
+ "type": "course.created",
+ "occurred_on": "2023-11-14 10:00:00",
+ "attributes": {
+ "id": "'"$courseId"'",
+ "name": "'"$courseName"'",
+ "duration": "'"$courseDuration"' days"
+ }
+ },
+ "meta": {
+ }
+ }
+ }'
+
+ echo "Created: $courseName"
+}
+
+while true; do
+ create_course &
+ sleep 0.001
+done
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/application/create/BackofficeCourseCreator.java b/src/backoffice/main/tv/codely/backoffice/courses/application/create/BackofficeCourseCreator.java
index f129d16a..496b8cb5 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/application/create/BackofficeCourseCreator.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/application/create/BackofficeCourseCreator.java
@@ -13,6 +13,8 @@ public BackofficeCourseCreator(BackofficeCourseRepository repository) {
}
public void create(String id, String name, String duration) {
- this.repository.save(new BackofficeCourse(id, name, duration));
+ if (this.repository.search(id).isEmpty()) {
+ this.repository.save(new BackofficeCourse(id, name, duration));
+ }
}
}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/application/rename/BackofficeCourseRenamer.java b/src/backoffice/main/tv/codely/backoffice/courses/application/rename/BackofficeCourseRenamer.java
new file mode 100644
index 00000000..e50c42f4
--- /dev/null
+++ b/src/backoffice/main/tv/codely/backoffice/courses/application/rename/BackofficeCourseRenamer.java
@@ -0,0 +1,26 @@
+package tv.codely.backoffice.courses.application.rename;
+
+import tv.codely.backoffice.courses.domain.BackofficeCourseNotFound;
+import tv.codely.backoffice.courses.domain.BackofficeCourseRepository;
+import tv.codely.shared.domain.Service;
+
+@Service
+public final class BackofficeCourseRenamer {
+ private final BackofficeCourseRepository repository;
+
+ public BackofficeCourseRenamer(BackofficeCourseRepository repository) {
+ this.repository = repository;
+ }
+
+ public void rename(String id, String name) {
+ this.repository.search(id)
+ .ifPresentOrElse(course -> {
+ course.rename(name);
+
+ this.repository.save(course);
+ },
+ () -> {
+ throw new BackofficeCourseNotFound(id);
+ });
+ }
+}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/application/rename/RenameBackofficeCourseOnCourseRenamed.java b/src/backoffice/main/tv/codely/backoffice/courses/application/rename/RenameBackofficeCourseOnCourseRenamed.java
new file mode 100644
index 00000000..c92e48d3
--- /dev/null
+++ b/src/backoffice/main/tv/codely/backoffice/courses/application/rename/RenameBackofficeCourseOnCourseRenamed.java
@@ -0,0 +1,21 @@
+package tv.codely.backoffice.courses.application.rename;
+
+import org.springframework.context.event.EventListener;
+import tv.codely.shared.domain.Service;
+import tv.codely.shared.domain.bus.event.DomainEventSubscriber;
+import tv.codely.shared.domain.course.CourseRenamedDomainEvent;
+
+@Service
+@DomainEventSubscriber({CourseRenamedDomainEvent.class})
+public final class RenameBackofficeCourseOnCourseRenamed {
+ private final BackofficeCourseRenamer renamer;
+
+ public RenameBackofficeCourseOnCourseRenamed(BackofficeCourseRenamer renamer) {
+ this.renamer = renamer;
+ }
+
+ @EventListener
+ public void on(CourseRenamedDomainEvent event) {
+ renamer.rename(event.aggregateId(), event.name());
+ }
+}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourse.java b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourse.java
index f97d7488..05f88b1c 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourse.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourse.java
@@ -7,7 +7,7 @@
public final class BackofficeCourse {
private final String id;
- private final String name;
+ private String name;
private final String duration;
public BackofficeCourse() {
@@ -30,6 +30,10 @@ public static BackofficeCourse fromPrimitives(Map plainData) {
);
}
+ public void rename(String newName) {
+ this.name = newName;
+ }
+
public String id() {
return id;
}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseNotFound.java b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseNotFound.java
new file mode 100644
index 00000000..f5596ffa
--- /dev/null
+++ b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseNotFound.java
@@ -0,0 +1,7 @@
+package tv.codely.backoffice.courses.domain;
+
+public class BackofficeCourseNotFound extends RuntimeException {
+ public BackofficeCourseNotFound(String id) {
+ super(String.format("The course <%s> doesn't exist", id));
+ }
+}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseRepository.java b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseRepository.java
index 2183d54a..36893521 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseRepository.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/domain/BackofficeCourseRepository.java
@@ -3,11 +3,14 @@
import tv.codely.shared.domain.criteria.Criteria;
import java.util.List;
+import java.util.Optional;
public interface BackofficeCourseRepository {
void save(BackofficeCourse course);
- List searchAll();
+ Optional search(String id);
+
+ List searchAll();
List matching(Criteria criteria);
}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepository.java b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepository.java
index cb84311a..c97dd85d 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepository.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepository.java
@@ -9,31 +9,37 @@
import tv.codely.shared.infrastructure.elasticsearch.ElasticsearchRepository;
import java.util.List;
+import java.util.Optional;
@Primary
@Service
public final class ElasticsearchBackofficeCourseRepository extends ElasticsearchRepository implements BackofficeCourseRepository {
- public ElasticsearchBackofficeCourseRepository(ElasticsearchClient client) {
- super(client);
- }
-
- @Override
- public void save(BackofficeCourse course) {
- persist(course.id(), course.toPrimitives());
- }
-
- @Override
- public List searchAll() {
- return searchAllInElastic(BackofficeCourse::fromPrimitives);
- }
-
- @Override
- public List matching(Criteria criteria) {
- return searchByCriteria(criteria, BackofficeCourse::fromPrimitives);
- }
-
- @Override
- protected String moduleName() {
- return "courses";
- }
+ public ElasticsearchBackofficeCourseRepository(ElasticsearchClient client) {
+ super(client);
+ }
+
+ @Override
+ public void save(BackofficeCourse course) {
+ persist(course.id(), course.toPrimitives());
+ }
+
+ @Override
+ public Optional search(String id) {
+ return this.searchById(id, BackofficeCourse::fromPrimitives);
+ }
+
+ @Override
+ public List searchAll() {
+ return searchAllInElastic(BackofficeCourse::fromPrimitives);
+ }
+
+ @Override
+ public List matching(Criteria criteria) {
+ return searchByCriteria(criteria, BackofficeCourse::fromPrimitives);
+ }
+
+ @Override
+ protected String moduleName() {
+ return "courses";
+ }
}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/InMemoryCacheBackofficeCourseRepository.java b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/InMemoryCacheBackofficeCourseRepository.java
index c616b49c..b645f5b4 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/InMemoryCacheBackofficeCourseRepository.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/InMemoryCacheBackofficeCourseRepository.java
@@ -7,46 +7,58 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Optional;
public final class InMemoryCacheBackofficeCourseRepository implements BackofficeCourseRepository {
- private final BackofficeCourseRepository repository;
- private List courses = new ArrayList<>();
- private HashMap> matchingCourses = new HashMap<>();
+ private final BackofficeCourseRepository repository;
+ private List courses = new ArrayList<>();
+ private HashMap> matchingCourses = new HashMap<>();
- public InMemoryCacheBackofficeCourseRepository(BackofficeCourseRepository repository) {
- this.repository = repository;
- }
+ public InMemoryCacheBackofficeCourseRepository(BackofficeCourseRepository repository) {
+ this.repository = repository;
+ }
- @Override
- public void save(BackofficeCourse course) {
- repository.save(course);
- }
+ @Override
+ public void save(BackofficeCourse course) {
+ repository.save(course);
+ }
- @Override
- public List searchAll() {
- return courses.isEmpty() ? searchAndFillCache() : courses;
- }
+ @Override
+ public List searchAll() {
+ return courses.isEmpty() ? searchAndFillCache() : courses;
+ }
- @Override
- public List matching(Criteria criteria) {
- return matchingCourses.containsKey(criteria.serialize())
- ? matchingCourses.get(criteria.serialize())
- : searchMatchingAndFillCache(criteria);
- }
+ public Optional search(String id) {
+ return courses.stream()
+ .filter(course -> course.id().equals(id))
+ .findFirst()
+ .or(() -> {
+ Optional course = repository.search(id);
+ course.ifPresent(courses::add);
+ return course;
+ });
+ }
- private List searchMatchingAndFillCache(Criteria criteria) {
- List courses = repository.matching(criteria);
+ @Override
+ public List matching(Criteria criteria) {
+ return matchingCourses.containsKey(criteria.serialize())
+ ? matchingCourses.get(criteria.serialize())
+ : searchMatchingAndFillCache(criteria);
+ }
- this.matchingCourses.put(criteria.serialize(), courses);
+ private List searchMatchingAndFillCache(Criteria criteria) {
+ List courses = repository.matching(criteria);
- return courses;
- }
+ this.matchingCourses.put(criteria.serialize(), courses);
- private List searchAndFillCache() {
- List courses = repository.searchAll();
+ return courses;
+ }
- this.courses = courses;
+ private List searchAndFillCache() {
+ List courses = repository.searchAll();
- return courses;
- }
+ this.courses = courses;
+
+ return courses;
+ }
}
diff --git a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/MySqlBackofficeCourseRepository.java b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/MySqlBackofficeCourseRepository.java
index bcb89765..a23fd771 100644
--- a/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/MySqlBackofficeCourseRepository.java
+++ b/src/backoffice/main/tv/codely/backoffice/courses/infrastructure/persistence/MySqlBackofficeCourseRepository.java
@@ -10,6 +10,7 @@
import tv.codely.shared.infrastructure.hibernate.HibernateRepository;
import java.util.List;
+import java.util.Optional;
@Service
@Transactional("backoffice-transaction_manager")
@@ -23,7 +24,12 @@ public void save(BackofficeCourse course) {
persist(course);
}
- @Override
+ @Override
+ public Optional search(String id) {
+ return byId(id);
+ }
+
+ @Override
public List searchAll() {
return all();
}
diff --git a/src/backoffice/main/tv/codely/backoffice/shared/infrastructure/persistence/BackofficeMySqlEventBusConfiguration.java b/src/backoffice/main/tv/codely/backoffice/shared/infrastructure/persistence/BackofficeMySqlEventBusConfiguration.java
index 4704f7b3..1113298e 100644
--- a/src/backoffice/main/tv/codely/backoffice/shared/infrastructure/persistence/BackofficeMySqlEventBusConfiguration.java
+++ b/src/backoffice/main/tv/codely/backoffice/shared/infrastructure/persistence/BackofficeMySqlEventBusConfiguration.java
@@ -4,6 +4,7 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
import tv.codely.shared.infrastructure.bus.event.DomainEventsInformation;
import tv.codely.shared.infrastructure.bus.event.mysql.MySqlDomainEventsConsumer;
import tv.codely.shared.infrastructure.bus.event.mysql.MySqlEventBus;
diff --git a/src/backoffice/test/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepositoryShould.java b/src/backoffice/test/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepositoryShould.java
index 5f632890..f94748b9 100644
--- a/src/backoffice/test/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepositoryShould.java
+++ b/src/backoffice/test/tv/codely/backoffice/courses/infrastructure/persistence/ElasticsearchBackofficeCourseRepositoryShould.java
@@ -7,56 +7,108 @@
import tv.codely.backoffice.courses.domain.BackofficeCourse;
import tv.codely.backoffice.courses.domain.BackofficeCourseCriteriaMother;
import tv.codely.backoffice.courses.domain.BackofficeCourseMother;
+import tv.codely.shared.domain.UuidMother;
+import tv.codely.shared.domain.WordMother;
import tv.codely.shared.domain.criteria.Criteria;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
final class ElasticsearchBackofficeCourseRepositoryShould extends BackofficeContextInfrastructureTestCase {
- @Autowired
- private ElasticsearchBackofficeCourseRepository repository;
+ @Autowired
+ private ElasticsearchBackofficeCourseRepository repository;
- @BeforeEach
- protected void setUp() throws IOException {
- clearElasticsearch();
- }
+ @BeforeEach
+ protected void setUp() throws IOException {
+ clearElasticsearch();
+ }
- @Test
- void save_a_course() {
- repository.save(BackofficeCourseMother.random());
- }
+ @Test
+ void save_a_course() {
+ repository.save(BackofficeCourseMother.random());
+ }
- @Test
- void search_all_existing_courses() throws Exception {
- BackofficeCourse course = BackofficeCourseMother.random();
- BackofficeCourse anotherCourse = BackofficeCourseMother.random();
+ @Test
+ void search_an_existing_course() throws Exception {
+ BackofficeCourse course = BackofficeCourseMother.random();
- List expected = Arrays.asList(course, anotherCourse);
+ repository.save(course);
- repository.save(course);
- repository.save(anotherCourse);
+ eventually(() -> assertEquals(Optional.of(course), repository.search(course.id())));
+ }
- eventually(() -> assertEquals(expected, repository.searchAll()));
- }
+ @Test
+ void update_an_existing_course() throws Exception {
+ BackofficeCourse course = BackofficeCourseMother.random();
- @Test
- void search_courses_using_a_criteria() throws Exception {
- BackofficeCourse matchingCourse = BackofficeCourseMother.create("DDD en Java", "3 days");
- BackofficeCourse anotherMatchingCourse = BackofficeCourseMother.create("DDD en TypeScript", "2.5 days");
- BackofficeCourse intellijCourse = BackofficeCourseMother.create("Exprimiendo Intellij", "48 hours");
- BackofficeCourse cobolCourse = BackofficeCourseMother.create("DDD en Cobol", "5 years");
+ repository.save(course);
+ course.rename(WordMother.random());
+ repository.save(course);
- Criteria criteria = BackofficeCourseCriteriaMother.nameAndDurationContains("DDD", "days");
- List expected = Arrays.asList(matchingCourse, anotherMatchingCourse);
+ eventually(() -> assertEquals(Optional.of(course), repository.search(course.id())));
+ }
- repository.save(matchingCourse);
- repository.save(anotherMatchingCourse);
- repository.save(intellijCourse);
- repository.save(cobolCourse);
+ @Test
+ void not_find_a_non_existing_course() {
+ assertEquals(Optional.empty(), repository.search(UuidMother.random()));
+ }
- eventually(() -> assertEquals(expected, repository.matching(criteria)));
- }
+ @Test
+ void search_all_existing_courses() throws Exception {
+ BackofficeCourse course = BackofficeCourseMother.random();
+ BackofficeCourse anotherCourse = BackofficeCourseMother.random();
+
+ List expected = Arrays.asList(course, anotherCourse);
+
+ repository.save(course);
+ repository.save(anotherCourse);
+
+ eventually(() -> {
+ List actual = repository.searchAll();
+
+ List sortedExpected = expected.stream()
+ .sorted(Comparator.comparing(BackofficeCourse::id))
+ .collect(Collectors.toList());
+ List sortedActual = actual.stream()
+ .sorted(Comparator.comparing(BackofficeCourse::id))
+ .collect(Collectors.toList());
+
+ assertEquals(sortedExpected, sortedActual);
+ });
+ }
+
+ @Test
+ void search_courses_using_a_criteria() throws Exception {
+ BackofficeCourse matchingCourse = BackofficeCourseMother.create("DDD en Java", "3 days");
+ BackofficeCourse anotherMatchingCourse = BackofficeCourseMother.create("DDD en TypeScript", "2.5 days");
+ BackofficeCourse intellijCourse = BackofficeCourseMother.create("Exprimiendo Intellij", "48 hours");
+ BackofficeCourse cobolCourse = BackofficeCourseMother.create("DDD en Cobol", "5 years");
+
+ Criteria criteria = BackofficeCourseCriteriaMother.nameAndDurationContains("DDD", "days");
+ List expected = Arrays.asList(matchingCourse, anotherMatchingCourse);
+
+ repository.save(matchingCourse);
+ repository.save(anotherMatchingCourse);
+ repository.save(intellijCourse);
+ repository.save(cobolCourse);
+
+ eventually(() -> {
+ List actual = repository.matching(criteria);
+
+ List sortedExpected = expected.stream()
+ .sorted(Comparator.comparing(BackofficeCourse::id))
+ .collect(Collectors.toList());
+ List sortedActual = actual.stream()
+ .sorted(Comparator.comparing(BackofficeCourse::id))
+ .collect(Collectors.toList());
+
+ assertEquals(sortedExpected, sortedActual);
+ });
+ }
}
diff --git a/src/mooc/main/tv/codely/mooc/courses_counter/application/increment/CoursesCounterIncrementer.java b/src/mooc/main/tv/codely/mooc/courses_counter/application/increment/CoursesCounterIncrementer.java
index c4433c07..2f80400d 100644
--- a/src/mooc/main/tv/codely/mooc/courses_counter/application/increment/CoursesCounterIncrementer.java
+++ b/src/mooc/main/tv/codely/mooc/courses_counter/application/increment/CoursesCounterIncrementer.java
@@ -8,22 +8,22 @@
@Service
public final class CoursesCounterIncrementer {
- private CoursesCounterRepository repository;
- private UuidGenerator uuidGenerator;
+ private CoursesCounterRepository repository;
+ private UuidGenerator uuidGenerator;
- public CoursesCounterIncrementer(CoursesCounterRepository repository, UuidGenerator uuidGenerator) {
- this.repository = repository;
- this.uuidGenerator = uuidGenerator;
- }
+ public CoursesCounterIncrementer(CoursesCounterRepository repository, UuidGenerator uuidGenerator) {
+ this.repository = repository;
+ this.uuidGenerator = uuidGenerator;
+ }
- public void increment(CourseId id) {
- CoursesCounter counter = repository.search()
- .orElseGet(() -> CoursesCounter.initialize(uuidGenerator.generate()));
+ public void increment(CourseId id) {
+ CoursesCounter counter = repository.search()
+ .orElseGet(() -> CoursesCounter.initialize(uuidGenerator.generate()));
- if (!counter.hasIncremented(id)) {
- counter.increment(id);
+ if (!counter.hasIncremented(id)) {
+ counter.increment(id);
- repository.save(counter);
- }
- }
+ repository.save(counter);
+ }
+ }
}
diff --git a/src/mooc/test/tv/codely/mooc/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusShould.java b/src/mooc/test/tv/codely/mooc/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusShould.java
index e5592563..70c8de26 100644
--- a/src/mooc/test/tv/codely/mooc/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusShould.java
+++ b/src/mooc/test/tv/codely/mooc/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusShould.java
@@ -46,7 +46,7 @@ void publish_and_consume_domain_events_from_rabbitmq() throws Exception {
eventBus.publish(Collections.singletonList(domainEvent));
- consumer.consume();
+ consumer.consume("mooc");
eventually(() -> assertTrue(subscriber.hasBeenExecuted));
}
diff --git a/src/shared/main/tv/codely/shared/domain/Utils.java b/src/shared/main/tv/codely/shared/domain/Utils.java
index 53dbc3ea..a3a56a6f 100644
--- a/src/shared/main/tv/codely/shared/domain/Utils.java
+++ b/src/shared/main/tv/codely/shared/domain/Utils.java
@@ -28,6 +28,14 @@ public static String jsonEncode(HashMap map) {
}
}
+ public static String jsonEncode(Object map) {
+ try {
+ return new ObjectMapper().writeValueAsString(map);
+ } catch (JsonProcessingException e) {
+ return "";
+ }
+ }
+
public static HashMap jsonDecode(String body) {
try {
return new ObjectMapper().readValue(body, HashMap.class);
diff --git a/src/shared/main/tv/codely/shared/domain/course/CourseRenamedDomainEvent.java b/src/shared/main/tv/codely/shared/domain/course/CourseRenamedDomainEvent.java
new file mode 100644
index 00000000..2fb40972
--- /dev/null
+++ b/src/shared/main/tv/codely/shared/domain/course/CourseRenamedDomainEvent.java
@@ -0,0 +1,78 @@
+package tv.codely.shared.domain.course;
+
+import tv.codely.shared.domain.bus.event.DomainEvent;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Objects;
+
+public final class CourseRenamedDomainEvent extends DomainEvent {
+ private final String name;
+
+ public CourseRenamedDomainEvent() {
+ super(null);
+
+ this.name = null;
+ }
+
+ public CourseRenamedDomainEvent(String aggregateId, String name) {
+ super(aggregateId);
+
+ this.name = name;
+ }
+
+ public CourseRenamedDomainEvent(
+ String aggregateId,
+ String eventId,
+ String occurredOn,
+ String name
+ ) {
+ super(aggregateId, eventId, occurredOn);
+
+ this.name = name;
+ }
+
+ @Override
+ public String eventName() {
+ return "course.renamed";
+ }
+
+ @Override
+ public HashMap toPrimitives() {
+ return new HashMap<>() {{
+ put("name", name);
+ }};
+ }
+
+ @Override
+ public CourseRenamedDomainEvent fromPrimitives(
+ String aggregateId,
+ HashMap body,
+ String eventId,
+ String occurredOn
+ ) {
+ return new CourseRenamedDomainEvent(
+ aggregateId,
+ eventId,
+ occurredOn,
+ (String) body.get("name")
+ );
+ }
+
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CourseRenamedDomainEvent that = (CourseRenamedDomainEvent) o;
+ return Objects.equals(name, that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/bus/event/DomainEventSubscribersInformation.java b/src/shared/main/tv/codely/shared/infrastructure/bus/event/DomainEventSubscribersInformation.java
index e7f5b923..88556f11 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/bus/event/DomainEventSubscribersInformation.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/bus/event/DomainEventSubscribersInformation.java
@@ -11,43 +11,44 @@
@Service
public final class DomainEventSubscribersInformation {
- HashMap, DomainEventSubscriberInformation> information;
-
- public DomainEventSubscribersInformation(HashMap, DomainEventSubscriberInformation> information) {
- this.information = information;
- }
-
- public DomainEventSubscribersInformation() {
- this(scanDomainEventSubscribers());
- }
-
- private static HashMap, DomainEventSubscriberInformation> scanDomainEventSubscribers() {
- Reflections reflections = new Reflections("tv.codely");
- Set> subscribers = reflections.getTypesAnnotatedWith(DomainEventSubscriber.class);
-
- HashMap, DomainEventSubscriberInformation> subscribersInformation = new HashMap<>();
-
- for (Class> subscriberClass : subscribers) {
- DomainEventSubscriber annotation = subscriberClass.getAnnotation(DomainEventSubscriber.class);
-
- subscribersInformation.put(
- subscriberClass,
- new DomainEventSubscriberInformation(subscriberClass, Arrays.asList(annotation.value()))
- );
- }
-
- return subscribersInformation;
- }
-
- public Collection all() {
- return information.values();
- }
-
- public String[] rabbitMqFormattedNames() {
- return information.values()
- .stream()
- .map(DomainEventSubscriberInformation::formatRabbitMqQueueName)
- .distinct()
- .toArray(String[]::new);
- }
+ HashMap, DomainEventSubscriberInformation> information;
+
+ public DomainEventSubscribersInformation(HashMap, DomainEventSubscriberInformation> information) {
+ this.information = information;
+ }
+
+ public DomainEventSubscribersInformation() {
+ this(scanDomainEventSubscribers());
+ }
+
+ private static HashMap, DomainEventSubscriberInformation> scanDomainEventSubscribers() {
+ Reflections reflections = new Reflections("tv.codely");
+ Set> subscribers = reflections.getTypesAnnotatedWith(DomainEventSubscriber.class);
+
+ HashMap, DomainEventSubscriberInformation> subscribersInformation = new HashMap<>();
+
+ for (Class> subscriberClass : subscribers) {
+ DomainEventSubscriber annotation = subscriberClass.getAnnotation(DomainEventSubscriber.class);
+
+ subscribersInformation.put(
+ subscriberClass,
+ new DomainEventSubscriberInformation(subscriberClass, Arrays.asList(annotation.value()))
+ );
+ }
+
+ return subscribersInformation;
+ }
+
+ public Collection all() {
+ return information.values();
+ }
+
+ public String[] rabbitMqFormattedNamesFor(String contextName) {
+ return information.values()
+ .stream()
+ .map(DomainEventSubscriberInformation::formatRabbitMqQueueName)
+ .distinct()
+ .filter(queueName -> queueName.contains("." + contextName + "."))
+ .toArray(String[]::new);
+ }
}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqDomainEventsConsumer.java b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqDomainEventsConsumer.java
index f613ecc2..d1620f3f 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqDomainEventsConsumer.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqDomainEventsConsumer.java
@@ -13,7 +13,6 @@
import tv.codely.shared.infrastructure.bus.event.DomainEventJsonDeserializer;
import tv.codely.shared.infrastructure.bus.event.DomainEventSubscribersInformation;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -21,13 +20,14 @@
@Service
public final class RabbitMqDomainEventsConsumer {
private final String CONSUMER_NAME = "domain_events_consumer";
- private final int MAX_RETRIES = 2;
+ private final int MAX_RETRIES = 10;
private final DomainEventJsonDeserializer deserializer;
private final ApplicationContext context;
private final RabbitMqPublisher publisher;
private final HashMap domainEventSubscribers = new HashMap<>();
RabbitListenerEndpointRegistry registry;
private DomainEventSubscribersInformation information;
+ private String contextName;
public RabbitMqDomainEventsConsumer(
RabbitListenerEndpointRegistry registry,
@@ -43,12 +43,14 @@ public RabbitMqDomainEventsConsumer(
this.publisher = publisher;
}
- public void consume() {
+ public void consume(String contextName) {
+ this.contextName = contextName;
+
AbstractMessageListenerContainer container = (AbstractMessageListenerContainer) registry.getListenerContainer(
CONSUMER_NAME
);
- container.addQueueNames(information.rabbitMqFormattedNames());
+ container.addQueueNames(information.rabbitMqFormattedNamesFor(contextName));
container.start();
}
@@ -68,14 +70,12 @@ public void consumer(Message message) throws Exception {
try {
subscriberOnMethod.invoke(subscriber, domainEvent);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException error) {
- throw new Exception(String.format(
- "The subscriber <%s> should implement a method `on` listening the domain event <%s>",
- queue,
- domainEvent.eventName()
- ));
+
+ System.out.println("ACK: Consumed correctly!");
} catch (Exception error) {
- handleConsumptionError(message, queue);
+ System.out.println("Error consuming");
+
+ handleConsumptionError(message, queue);
}
}
@@ -92,10 +92,14 @@ private void handleConsumptionError(Message message, String queue) {
}
private void sendToRetry(Message message, String queue) {
+ System.out.println("SENDING TO RETRY: " + contextName + " - " + queue);
+
sendMessageTo(RabbitMqExchangeNameFormatter.retry("domain_events"), message, queue);
}
private void sendToDeadLetter(Message message, String queue) {
+ System.out.println("SENDING TO DEAD LETTER: " + contextName + " - " + queue);
+
sendMessageTo(RabbitMqExchangeNameFormatter.deadLetter("domain_events"), message, queue);
}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBus.java b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBus.java
index 47d1738f..2bad6fd2 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBus.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBus.java
@@ -1,6 +1,8 @@
package tv.codely.shared.infrastructure.bus.event.rabbitmq;
import org.springframework.amqp.AmqpException;
+import org.springframework.context.annotation.Primary;
+import tv.codely.shared.domain.Service;
import tv.codely.shared.domain.bus.event.DomainEvent;
import tv.codely.shared.domain.bus.event.EventBus;
import tv.codely.shared.infrastructure.bus.event.mysql.MySqlEventBus;
@@ -8,27 +10,29 @@
import java.util.Collections;
import java.util.List;
+@Primary
+@Service
public class RabbitMqEventBus implements EventBus {
- private final RabbitMqPublisher publisher;
- private final MySqlEventBus failoverPublisher;
- private final String exchangeName;
+ private final RabbitMqPublisher publisher;
+ private final MySqlEventBus failoverPublisher;
+ private final String exchangeName;
- public RabbitMqEventBus(RabbitMqPublisher publisher, MySqlEventBus failoverPublisher) {
- this.publisher = publisher;
- this.failoverPublisher = failoverPublisher;
- this.exchangeName = "domain_events";
- }
+ public RabbitMqEventBus(RabbitMqPublisher publisher, MySqlEventBus failoverPublisher) {
+ this.publisher = publisher;
+ this.failoverPublisher = failoverPublisher;
+ this.exchangeName = "domain_events";
+ }
- @Override
- public void publish(List events) {
- events.forEach(this::publish);
- }
+ @Override
+ public void publish(List events) {
+ events.forEach(this::publish);
+ }
- private void publish(DomainEvent domainEvent) {
- try {
- this.publisher.publish(domainEvent, exchangeName);
- } catch (AmqpException error) {
- failoverPublisher.publish(Collections.singletonList(domainEvent));
- }
- }
+ private void publish(DomainEvent domainEvent) {
+ try {
+ this.publisher.publish(domainEvent, exchangeName);
+ } catch (AmqpException error) {
+ failoverPublisher.publish(Collections.singletonList(domainEvent));
+ }
+ }
}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusConfiguration.java b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusConfiguration.java
index 4fe9688a..f95e1888 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusConfiguration.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/bus/event/rabbitmq/RabbitMqEventBusConfiguration.java
@@ -128,7 +128,7 @@ private HashMap retryQueueArguments(TopicExchange exchange, Stri
return new HashMap() {{
put("x-dead-letter-exchange", exchange.getName());
put("x-dead-letter-routing-key", routingKey);
- put("x-message-ttl", 1000);
+ put("x-message-ttl", 3000);
}};
}
}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/bus/event/spring/SpringApplicationEventBus.java b/src/shared/main/tv/codely/shared/infrastructure/bus/event/spring/SpringApplicationEventBus.java
index 0b2a16a4..56a6205e 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/bus/event/spring/SpringApplicationEventBus.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/bus/event/spring/SpringApplicationEventBus.java
@@ -1,14 +1,12 @@
package tv.codely.shared.infrastructure.bus.event.spring;
import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.context.annotation.Primary;
import tv.codely.shared.domain.Service;
import tv.codely.shared.domain.bus.event.DomainEvent;
import tv.codely.shared.domain.bus.event.EventBus;
import java.util.List;
-@Primary
@Service
public class SpringApplicationEventBus implements EventBus {
private final ApplicationEventPublisher publisher;
diff --git a/src/shared/main/tv/codely/shared/infrastructure/cli/ConsoleCommand.java b/src/shared/main/tv/codely/shared/infrastructure/cli/ConsoleCommand.java
index 45468089..dd90a889 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/cli/ConsoleCommand.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/cli/ConsoleCommand.java
@@ -4,22 +4,22 @@
@Service
public abstract class ConsoleCommand {
- private static final String ANSI_RESET = "\u001B[0m";
- private static final String ANSI_RED = "\u001B[31m";
- private static final String ANSI_CYAN = "\u001B[36m";
- private static final String ANSI_GREEN = "\u001B[32m";
+ private static final String ANSI_RESET = "\u001B[0m";
+ private static final String ANSI_RED = "\u001B[31m";
+ private static final String ANSI_CYAN = "\u001B[36m";
+ private static final String ANSI_GREEN = "\u001B[32m";
- abstract public void execute(String[] args);
+ abstract public void execute(String[] args);
- protected void log(String text) {
- System.out.println(String.format("%s%s%s", ANSI_GREEN, text, ANSI_RESET));
- }
+ protected void log(String text) {
+ System.out.println(String.format("%s%s%s", ANSI_GREEN, text, ANSI_RESET));
+ }
- protected void info(String text) {
- System.out.println(String.format("%s%s%s", ANSI_CYAN, text, ANSI_RESET));
- }
+ protected void info(String text) {
+ System.out.println(String.format("%s%s%s", ANSI_CYAN, text, ANSI_RESET));
+ }
- protected void error(String text) {
- System.out.println(String.format("%s%s%s", ANSI_RED, text, ANSI_RESET));
- }
+ protected void error(String text) {
+ System.out.println(String.format("%s%s%s", ANSI_RED, text, ANSI_RESET));
+ }
}
diff --git a/src/shared/main/tv/codely/shared/infrastructure/elasticsearch/ElasticsearchRepository.java b/src/shared/main/tv/codely/shared/infrastructure/elasticsearch/ElasticsearchRepository.java
index 3f4730a6..c87903b0 100644
--- a/src/shared/main/tv/codely/shared/infrastructure/elasticsearch/ElasticsearchRepository.java
+++ b/src/shared/main/tv/codely/shared/infrastructure/elasticsearch/ElasticsearchRepository.java
@@ -1,5 +1,7 @@
package tv.codely.shared.infrastructure.elasticsearch;
+import org.elasticsearch.action.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
@@ -27,7 +29,25 @@ protected List searchAllInElastic(Function