Git Product home page Git Product logo

eventuate-tram-core's Introduction

An Eventuate project

logo

This project is part of Eventuate, which is a microservices collaboration platform.

Eventuate Tram (Transactional Messaging) platform

Spring/Micronaut

eventuate tram bom

Quarkus

eventuate tram quarkus bom

Eventuate Tram is a platform that solves the distributed data management problems inherent in a microservice architecture.

It is described in more detail in my book Microservice Patterns and the getting started guide.

Key benefits of Eventuate Tram

Maintain data consistency using sagas

Implement commands that update data in multiple microservices by using Sagas, which are sequences of local transactions coordinated using messages

Implement queries using CQRS

Implement queries that retrieve data from multiple services by using CQRS views, which are easily queryable replicas maintained using events

Communicate using transactional messaging

Reliably send and receive messages and events as part of a database transaction by using the Transactional Outbox pattern

How it works

Eventuate Tram provides several messaging abstractions:

  • messaging - send and receive messages over named channels

  • events - publish domain events and subscribe to domain events

  • commands - asynchronously send a command to a service and receive a reply

Eventuate Tram messaging implements the Transactional Outbox pattern. An message producer inserts events into an OUTBOX table as part of the ACID transaction that updates data, such as JPA entities. A separate message relay (a.k.a. Eventuate CDC service) publishes messages to the message broker.

ReliablePublication

The Eventuate CDC service works in one of two ways:

Supported technologies

Languages:

Databases:

Message brokers:

  • Apache Kafka

  • ActiveMQ

  • RabbitMQ

  • Redis Streams

Getting started

Please see the getting started guide.

Example applications

There are numerous example applications:

Got questions?

Don’t hesitate to create an issue or see

Need support?

Take a look at the available paid support options.

Transactional messaging

Send a message using MessageProducer:

public interface MessageProducer {
  void send(String destination, Message message);
}

Receive messages using:

public interface MessageConsumer {
  void subscribe(String subscriberId, Set<String> channels, MessageHandler handler);
}

See this example of transactional messaging.

Transactional domain events

The domain event package builds on the core APIs.

Publish domain events using the DomainEventPublisher interface:

public interface DomainEventPublisher {

  void publish(String aggregateType, Object aggregateId, List<DomainEvent> domainEvents);
  ...

Subscribe to domain events using a DomainEventDispatcher:

public class DomainEventDispatcher {
    public DomainEventDispatcher(String eventDispatcherId,
                DomainEventHandlers eventHandlers,
                ...) {
...
}

Handle the events using DomainEventHandlers:

public class RestaurantOrderEventConsumer {

  public DomainEventHandlers domainEventHandlers() {
    return DomainEventHandlersBuilder
            .forAggregateType("net.chrisrichardson.ftgo.restaurantservice.Restaurant")
            .onEvent(RestaurantMenuRevised.class, this::reviseMenu)
            .build();
  }

  public void reviseMenu(DomainEventEnvelope<RestaurantMenuRevised> de) {

See this example of transaction events.

Transactional commands

Transaction commands are implemented using transactional messaging.

Send a command using a CommandProducer:

public interface CommandProducer {
  String send(String channel, Command command, String replyTo, Map<String, String> headers);
  ...
}

Subscribe to commands using a CommandDispatcher:

public class CommandDispatcher {

  public CommandDispatcher(String commandDispatcherId,
           CommandHandlers commandHandlers) {
  ...
}

Handle commands and send a reply using CommandHandlers:

public class OrderCommandHandlers {


  public CommandHandlers commandHandlers() {
    return CommandHandlersBuilder
          .fromChannel("orderService")
          .onMessage(ApproveOrderCommand.class, this::approveOrder)
          ...
          .build();
  }

  public Message approveOrder(CommandMessage<ApproveOrderCommand> cm) {
    ApproveOrderCommand command = cm.getCommand();
    ...
  }

See this example of transactional commands.

Maven/Gradle artifacts

The artifacts are in JCenter. The latest version is:

RC

download

Release

download

There are the following API artifacts:

  • io.eventuate.tram.core:eventuate-tram-messaging:$eventuateTramVersion - core messaging APIs

  • io.eventuate.tram.core:eventuate-tram-events:$eventuateTramVersion - domain event API

  • io.eventuate.tram.core:eventuate-tram-commands:$eventuateTramVersion - commands/reply API

There are the following 'implementation' artifacts:

  • io.eventuate.tram.core:eventuate-tram-jdbc-kafka:$eventuateTramVersion - JDBC database and Apache Kafka message broker

  • io.eventuate.tram.core:eventuate-tram-jdbc-activemq:$eventuateTramVersion - JDBC database and Apache ActiveMQ message broker

  • io.eventuate.tram.core:eventuate-tram-jdbc-rabbitmq:$eventuateTramVersion - JDBC database and RabbitMQ message broker

  • io.eventuate.tram.core:eventuate-tram-jdbc-redis:$eventuateTramVersion - JDBC database and Redis Streams

  • io.eventuate.tram.core:eventuate-tram-in-memory:$eventuateTramVersion - In-memory JDBC database and in-memory messaging for testing

Running the CDC service

In addition to a database and message broker, you will need to run the Eventuate Tram CDC service. It reads events inserted into the database and publishes them to the message broker. It is written using Spring Boot. The easiest way to run this service during development is to use Docker Compose. The Eventuate Tram Code Basic examples project has an example docker-compose.yml file.

Contributing

Contributions are welcome.

eventuate-tram-core's People

Contributors

artemsidorkin avatar cer avatar dartartem avatar kwonglau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eventuate-tram-core's Issues

eventuate-tram-cdc-mysql-service will exit if it cannot connect to kafka on startup

When eventuate-tram-cdc-mysql-service starts and cannot connect to Kafka it will exit.
Perhaps it should loop/retry?

Caused by: org.apache.kafka.common.KafkaException: Failed to construct kafka producer
	at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:335)
	at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:188)
	at io.eventuate.local.java.kafka.producer.EventuateKafkaProducer.<init>(EventuateKafkaProducer.java:31)
	at io.eventuate.tram.cdc.mysql.connector.MessageTableChangesToDestinationsConfiguration.eventuateKafkaProducer(MessageTableChangesToDestinationsConfiguration.java:84)
	at io.eventuate.tram.cdc.mysql.connector.MessageTableChangesToDestinationsConfiguration$$EnhancerBySpringCGLIB$$824648f0.CGLIB$eventuateKafkaProducer$5(<generated>)
	at io.eventuate.tram.cdc.mysql.connector.MessageTableChangesToDestinationsConfiguration$$EnhancerBySpringCGLIB$$824648f0$$FastClassBySpringCGLIB$$1c3701eb.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
	at io.eventuate.tram.cdc.mysql.connector.MessageTableChangesToDestinationsConfiguration$$EnhancerBySpringCGLIB$$824648f0.eventuateKafkaProducer(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
	... 27 common frames omitted
Caused by: org.apache.kafka.common.config.ConfigException: No resolvable bootstrap urls given in bootstrap.servers
	at org.apache.kafka.clients.ClientUtils.parseAndValidateAddresses(ClientUtils.java:59)
	at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:275)
	... 40 common frames omitted

Spring 2.1.x => duplicate bean error

***************************

APPLICATION FAILED TO START

***************************

 

Description:

 

The bean 'eventuateSchema', defined in io.eventuate.tram.messaging.producer.jdbc.TramMessageProducerJdbcConfiguration, could not be registered. A bean with that name has already been defined in io.eventuate.tram.consumer.kafka.TramConsumerKafkaConfiguration and overriding is disabled.

 

Action:

 

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

.NET core support

Are there any plans for adding a .NET core version of eventuate tram? I have a mix of java and .net core services.

The size of 1000 for the payload column in the message table seems too small

We are having to increase the size of the payload column to fit some of our larger messages. We are creating the payload column like this:
payload NVARCHAR(MAX) NOT NULL
(we are using MSSQL)

Is there any reason why this would cause a problem?
Why is the length of 1000 chosen in the official setup script in the repository? Can it be changed to NVARCHAR(MAX)?

"oldDebeziumDbHistoryTopicName" in 0.20.0.M6 make cdc service startup with error

I tried example TODO list (https://github.com/eventuate-tram/eventuate-tram-examples-java-spring-todo-list)
with latest version of eventuate tram 0.20.0.M6, which is currently the master veresion of eventuate-tram-core
see the docker-compose yml attached:

tramcdcservice:
image: eventuateio/eventuate-tram-cdc-mysql-service:0.20.0.M6
container_name: cdcservice
restart: unless-stopped
ports:
- "8099:8080"
links:
- mysql
- kafka
- zookeeper
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql/eventuate
SPRING_DATASOURCE_USERNAME: mysqluser
SPRING_DATASOURCE_PASSWORD: mysqlpw
SPRING_DATASOURCE_DRIVER_CLASS_NAME: com.mysql.jdbc.Driver
EVENTUATELOCAL_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
EVENTUATELOCAL_ZOOKEEPER_CONNECTION_STRING: zookeeper:2181
EVENTUATELOCAL_CDC_DB_USER_NAME: root
EVENTUATELOCAL_CDC_DB_PASSWORD: rootpassword
EVENTUATELOCAL_CDC_BINLOG_CLIENT_ID: 1234567890
EVENTUATELOCAL_CDC_SOURCE_TABLE_NAME: message

When I start the eventuate containers, cdcservice throws an error that:

cdcservice |
cdcservice | Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
cdcservice | 02:46:47.871 [main] ERROR o.s.boot.SpringApplication - Application startup failed
cdcservice | org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cdcPipelineConfigurator': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: oldDebeziumDbHistoryTopicName must not be blank (set 'none' to not migrate debezium offset storage data)
cdcservice | at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137)
cdcservice | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
...
cdcservice | at org.springframework.boot.SpringApplication.run(SpringApplication.java:1176)
cdcservice | at io.eventuate.local.mysql.binlog.main.EventuateLocalCdcMysqlBinlogMain.main(EventuateLocalCdcMysqlBinlogMain.java:14)
cdcservice | at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
cdcservice | Caused by: java.lang.IllegalArgumentException: oldDebeziumDbHistoryTopicName must not be blank (set 'none' to not migrate debezium offset storage data)
cdcservice | at org.springframework.util.Assert.hasLength(Assert.java:157)
cdcservice | at io.eventuate.local.unified.cdc.pipeline.dblog.mysqlbinlog.properties.MySqlBinlogCdcPipelineReaderProperties.validate(MySqlBinlogCdcPipelineReaderProperties.java:16)
cdcservice | at io.eventuate.local.unified.cdc.pipeline.CdcPipelineConfigurator.createStartSaveCdcDefaultPipelineReader(CdcPipelineConfigurator.java:163)
cdcservice | at io.eventuate.local.unified.cdc.pipeline.CdcPipelineConfigurator.lambda$initialize$0(CdcPipelineConfigurator.java:72)
cdcservice | at java.util.Optional.orElseGet(Optional.java:267)
cdcservice | at io.eventuate.local.unified.cdc.pipeline.CdcPipelineConfigurator.initialize(CdcPipelineConfigurator.java:71)
cdcservice | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
cdcservice | at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134)
cdcservice | ... 26 common frames omitted

The issues I have are:

any suggestion would be appreciated, thanks in advanced.

Clean up dependencies on ":eventuate-tram-spring-consumer-common"

":eventuate-tram-spring-consumer-common" should not be a direct dependency of eventuate-<framework>-jdbc-<message-broker>.

compile project(":eventuate-tram-spring-consumer-common")

It's already in eventuate-spring-consumer-kafka so this particular one is a duplicate.

But I don't think it's in other eventuate-spring-consumer-<message-broker>, which is a problem for projects that use eventuate-spring-consumer-<message-broker>

But then it appears to be a dependency of non-spring eventuate-tram-<activemq/rabbitmq/redis> projects! Not a problem yet since there are micronaut versions of them.

An optimization implementation of saga

Hey,we have studied your framework in recent days and very appreciate your ideas and work on maintaining the consistency of transactions in the microservice architecture. Surprisingly, this is exactly what we are doing currently,we will add the new feature of transactional message in our project to ensure the eventual consistency of transaction in the microservice architecture.

In the process of realizing our ideas in rocketMQ, we also discovered that some issues have troubled us for a long time,so we did a lot of work in the following areas:

  1. API abstraction
    In order to simplify the usage and shield the underlying implementation,we only provided several APIs for users,but users can use these APIs to complete various operations,ranging from traditional pub/sub scenarios to high volume real-time zero-loss tolerance transaction system scenarios.

  2. Message reply mechanism
    As a zero-loss tolerance transaction system, our product naturally have a complete message reply mechanism that can be used in the event sourcing architecture or other architecture based on message. We also support strict ordering of messages, and can scale out gracefully.

  3. Simplify the programming model
    We also made a lot of efforts to simplify the programming model,especially in transactional messaging.

According to my understanding,our transactional message feature maybe give a awesome complementation for the SAGA pattern, and at the same time, our product at least can provide you with some infrastructure like kafka .etc. But we also found some defects about saga:saga pattern made programming model is more complex,and in order to be reliable,a service must atomically update its database and publish an event, it cannot use the traditional mechanism of a distributed transaction that spans the database and the message broker, so developers have to introduce other design patterns to achieve this. So could you give us some advice on combining saga patten with MQ, for simplify the programming model.

MSSQL scripts create a primary key that exceeds maximum allowed length

This part of the mssql database setup script:

CREATE TABLE eventuate.received_messages (
  consumer_id VARCHAR(767),
  message_id VARCHAR(767),
  PRIMARY KEY(consumer_id, message_id),
  creation_time BIGINT
);

Results in the following warning when executed:
Warning! The maximum key length for a clustered index is 900 bytes. The index 'PK__received__D66E66C3EEEEDFD7' has maximum length of 1534 bytes. For some combination of large values, the insert/update operation will fail.
I'm not sure why a length of 767 was chosen for the id columns, but since it is a composite key with 2 columns of length 767, it exceeds the maximum allowed length of 900.

Perhaps the id fields should have a length of 450 each?

Would this support Oracle?

Alternatively, Is It possible that the business services run with Oracle and sync the data about Eventuate Tram to MySQL for cdc service polling?

Postgres image is failing to build

See https://circleci.com/gh/eventuate-tram/eventuate-tram-core/45

Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libprotobuf-c-dev : Depends: libprotobuf-c1 (= 1.2.1-2) but 1.3.1-1 is to be installed
E: Unable to correct problems, you have held broken packages.
ERROR: Service 'postgres' failed to build: The command '/bin/sh -c apt-get update     && apt-get install -f -y --no-install-recommends         software-properties-common         build-essential         pkg-config         git         postgresql-server-dev-9.6         libproj-dev     && apt-get clean && apt-get update && apt-get install -f -y --no-install-recommends         liblwgeom-dev     && add-apt-repository "deb http://ftp.debian.org/debian testing main contrib"     && apt-get install nano     && apt-get update && apt-get install -f -y --no-install-recommends         libprotobuf-c-dev=1.2.*     && rm -rf /var/lib/apt/lists/*' returned a non-zero code: 100
Exited with code 1

Please, improve documentation

The framework is not very well documented. Examples are not very well explained, sources don't have javadocs, etc.

Please, consider improving documentation as it is very difficult to adopt this technology if things are not explained.

Thank you very much!

Python core support

this project seems to be very interesting for my project,

But, are there any plans for adding a python core version of eventuate tram?

Thanks a lot lot in advance

Make ObjectMapper injectable

I couldn't find a way to deserialize more complex types like org.javamoney.moneta.Money.
I would be better to inject JSonMapper and ObjectMapper in JSonMapper so that Jackson MixIns can be used.

java.util.ConcurrentModificationException when accessing message headers

A rarely occurring problem.

I suspect that it's because TracingMessagingInterceptor is calling Message.setHeader() which is modifying the headers map in place instead of copy on write.

2019-05-22 14:54:27.839  INFO [-,872bce8c71ae4ce4,872bce8c71ae4ce4,false] 40397 --- [    Test worker] i.e.tram.inmemory.InMemoryMessaging      : sending to channel kitchenService that has 1 subscriptions this message io.eventuate.tram.messaging.common.MessageImpl@2de6110f[payload={"orderId":99,"restaurantId":1,"ticketDetails":{"lineItems":[{"menuItemId":"1","name":"Chicken Vindaloo","quantity":5}]}},headers={command_saga_id=4fafb019b3bd16db-1633daefc8566c3e, DATE=Wed, 22 May 2019 21:54:27 GMT, command_type=net.chrisrichardson.ftgo.kitchenservice.api.CreateTicket, X-B3-SpanId=872bce8c71ae4ce4, command_reply_to=net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply, DESTINATION=kitchenService, command_saga_type=net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga, X-B3-Sampled=0, X-B3-TraceId=872bce8c71ae4ce4, ID=0000016ae189d57f-aea3cfd9f7110000}] 
2019-05-22 14:54:27.840  INFO [-,872bce8c71ae4ce4,872bce8c71ae4ce4,false] 40397 --- [    Test worker] i.e.tram.inmemory.InMemoryMessaging      : sending to channel kitchenService that has 1 subscriptions this message io.eventuate.tram.messaging.common.MessageImpl@2de6110f[payload={"orderId":99,"restaurantId":1,"ticketDetails":{"lineItems":[{"menuItemId":"1","name":"Chicken Vindaloo","quantity":5}]}},headers={command_saga_id=4fafb019b3bd16db-1633daefc8566c3e, DATE=Wed, 22 May 2019 21:54:27 GMT, command_type=net.chrisrichardson.ftgo.kitchenservice.api.CreateTicket, X-B3-SpanId=872bce8c71ae4ce4, command_reply_to=net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga-reply, DESTINATION=kitchenService, command_saga_type=net.chrisrichardson.ftgo.orderservice.sagas.createorder.CreateOrderSaga, X-B3-Sampled=0, X-B3-TraceId=872bce8c71ae4ce4, ID=0000016ae189d57f-aea3cfd9f7110000}] 
2019-05-22 14:54:27.845 ERROR [-,,,] 40397 --- [pool-2-thread-1] i.e.tram.inmemory.InMemoryMessaging      : message handler kitchenService

java.util.ConcurrentModificationException: null
	at java.base/java.util.HashMap$EntrySpliterator.forEachRemaining(HashMap.java:1756) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[na:na]
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578) ~[na:na]
	at io.eventuate.tram.commands.consumer.CommandDispatcher.correlationHeaders(CommandDispatcher.java:144) ~[eventuate-tram-commands-0.21.0.RELEASE.jar:na]
	at io.eventuate.tram.commands.consumer.CommandDispatcher.messageHandler(CommandDispatcher.java:80) ~[eventuate-tram-commands-0.21.0.RELEASE.jar:na]
	at io.eventuate.tram.sagas.participant.SagaCommandDispatcher.messageHandler(SagaCommandDispatcher.java:47) ~[eventuate-tram-sagas-participant-0.11.1.RELEASE.jar:na]
	at io.eventuate.tram.inmemory.InMemoryMessaging.lambda$null$0(InMemoryMessaging.java:83) ~[eventuate-tram-in-memory-0.20.0.RELEASE.jar:na]
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.0.7.RELEASE.jar:5.0.7.RELEASE]
	at io.eventuate.tram.inmemory.InMemoryMessaging.lambda$sendToHandlers$1(InMemoryMessaging.java:80) ~[eventuate-tram-in-memory-0.20.0.RELEASE.jar:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
	at java.base/java.lang.Thread.run(Thread.java:844) ~[na:na]

occurre two underscore in command header

It's a very minor issue.

You need to modify "_destination" to "destination" in CommandMessageHeaders.java.

Here is an example:

{
   "correlationHeaders": {
     "commandreply_saga_id": "0000016f2209f736-309c238fb9560000",
     "commandreply__destination": "accountingService", <--- here
     "commandreply_reply_to": "com.uplus.sample.notx.orderservice.sagas.createorder.CreateOrderSaga-reply",
     "commandreply_type": "com.uplus.sample.notx.accountingservice.api.AuthorizeCommand",
     "commandreply_saga_type": "com.uplus.sample.notx.orderservice.sagas.createorder.CreateOrderSaga",
     "reply_to_message_id": "0000016f2209fb89-309c238fb9560000"
   }
}

How to set up the Eventuate databases?

Key points:

  • Each service should have its own schema
  • Each service could have its own DB instance but that is not mandatory
  • The easier option is for the Eventuate tables to be in the same schema as the service's tables. But each service could have a second schema for just Eventuate tables. There is a property eventuate.database.schema/EVENTUATE_DATABASE_SCHEMA that controls that
  • You need to define the schema - its not created automatically

Take a look at https://github.com/microservices-patterns/ftgo-application/tree/master/mysql

Mongodb

could I use it as a database for Eventualy mongodb?

Simplify Eventuate Consumer @Configuration classes

Currently, an application has to @Import:

  • TramConsumerCommonConfiguration
  • MessageConsumerKafkaConfiguration
  • EventuateTramKafkaMessageConsumerConfiguration

it should only need to import EventuateTramKafkaMessageConsumerConfiguration

Duplicate eventuateCommonJdbcOperations bean in Eventuate Local and Eventuate Tram

I still see below error with those dependencies.

The bean 'eventuateCommonJdbcOperations', defined in io.eventuate.common.jdbckafkastore.EventuateLocalConfiguration, could not be registered. A bean with that name has already been defined in class path resource [io/eventuate/tram/messaging/producer/jdbc/TramMessageProducerJdbcConfiguration.class] and overriding is disabled.

Now the conflicting jars are,

eventuate-local-java-jdbc-0.31.0.RC3 --> EventuateLocalConfiguration --> eventuateCommonJdbcOperations()
and
eventuate-tram-producer-jdbc-0.22.0.RC5 -->  TramMessageProducerJdbcConfiguration --> eventuateCommonJdbcOperations()

Originally posted by @kushan-athukorala in #29 (comment)

Would be great to avoid sharing the commands between participants

In all examples of the eventuate-tram-commands module, both producers and consumers share common classes. The problem is that it might happen that this classes cannot be shared. Maybe, commands could be just strings, instead of classes. This would allow, for example, having participants written in different languages (obviously, using a port of this framework, or a custom implementation that know how to "talk" the same high-level protocol).

MSSQL scripts should use nvarchar instead of varchar

I think the equivalent to a varchar column in MySQL/PostgreSQL is an nvarchar column in MSSQL, not varchar. In MSSQL, nvarchar is required for full unicode support. I'm especially concerned about the message.payload and message.headers columns, since they could potentially include foreign characters (e.g. names, etc.). Perhaps the message.destination column should possibly also by changed to nvarchar, I'm not sure what Kafka supports for topic names. The id columns could potentially be OK to leave as varchar.

Missing publisher/subscriber mechanism for events/messages

It is not possible to publish an event which will be handled more than one service. In other words if one service(Service A) publishes the event/message, and many other services are subscribed to this event (B and C), only one service will receive it.

Tested with MySql polling, kafka.

ActiveMQ production code is incomplete

Message from Chris:

I see this pattern frequently:

public MessageConsumerActiveMQImpl(String url,
Optional user,
Optional password) {
this(url, Collections.emptyMap(), user, password);
}

public MessageConsumerActiveMQImpl(String url,
Map<String, ChannelType> messageModes,
Optional user,
Optional password) {
....
}

A class has two constructors. One is used by tests, the other by production code.

There really should be just one constructor (or to be more precise - constructors needed by production code). Generally, its the most general one, e.g. with the most parameters: in this case its the second constructor. If the tests needs a different constructor then the test code should define a factory method that calls the constructor.

What's weird about this MessageConsumerActiveMQImpl is that the production code uses the simpler constructor: messageModes is always empty. This means one of two things:

MessageConsumerActiveMQImpl implements unused functionality and can be simplified - along with the tests
The production code is incomplete and needs to support the configuration of different ChannelTypes.

I suspect its #2

Rethink transactional.noop.duplicate.message.detector.factory.enabled

This seems pretty ugly: https://github.com/eventuate-tram/eventuate-tram-docs/blob/master/src/docs/asciidoc/getting-started-eventuate-tram.adoc#micronaut-3

I understand that Micronaut searches the classpath for beans/factories - no @import

This is the fallback NoopDuplicateMessageDetector and is only defined if there is no other bean.
The developer can use it by not adding eventuate-tram-micronaut-consumer-jdbc as a dependency.

If the developer wants either of these:

  • SqlTableBasedDuplicateMessageDetector
  • TransactionalNoopDuplicateMessageDetector

Then they have add eventuate-tram-micronaut-consumer-jdbc as a dependency.

It seems ugly to have a boolean flag.
What would be cleaner would be a property like transactional.duplicate.detector.factory:

  • Unset or sqlTable -> use SqlTableBasedDuplicateMessageDetector
  • noop -> use TransactionalNoopDuplicateMessageDetector

Does @Requires support Unset or sqlTable` - time to read the manual?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.