itswuanran/enode
50.5
Weak · 22 September 2026
15.6k
lines of production code
Kotlin
with Java
7
measurements over time
What this system is
Enode is an event-driven framework for building distributed systems using the Command and Event Sourcing patterns. It provides a unified infrastructure for asynchronous command processing, domain event handling, and message queue integration across multiple backends including Kafka, RabbitMQ, and Redis. The system supports various event stores such as MySQL, PostgreSQL, MongoDB, and in-memory implementations, all configured via Spring Boot auto-configuration. The core domain and messaging layers have been modernized in Kotlin to support non-blocking, coroutine-based execution.
How it got here
2019 — Framework modernization and sample migration
26 changes.
The project underwent a significant architectural shift, removing legacy Java command processing and MySQL-specific schemas in favor of a multi-backend, annotation-driven framework. This period focused on rewriting message queue integrations in Kotlin, introducing new core APIs and exception handling, and replacing old samples with a modernized bank-transfer example.
2020 — Kotlin migration and async support
18 changes.
The project underwent a comprehensive migration of its core subsystems—including commanding, domain, eventing, and messaging—to Kotlin, leveraging coroutines for asynchronous processing. This period also introduced extensive test coverage and configuration support for various event stores and message queues, alongside new in-memory and JDBC/PostgreSQL/MongoDB implementations.
2021–2023 — Kotlin migration and queue integration
15 changes.
This period focused on migrating the framework's core domain and queue modules to Kotlin, introducing new abstractions for aggregate management and message handling. It also expanded the system's capabilities by adding support for multiple message brokers (AMQP, Ons, Pulsar, TCP, Redis) and implementing comprehensive metrics monitoring for observability.
Features
Add JDBC-based event and version store implementations
The JDBC module now includes new Kotlin implementations for the event store and published version store: JDBCEventStore, JDBCPublishedVersionStore, and their associated handlers. These classes provide the underlying persistence logic for domain events and aggregate published versions using SQL client operations, enabling users to persist event-sourced data in a relational database.
jdbc · high confidence
Add Kafka, RocketMQ, and JDBC event consumer configurations
The event-consumer sample now includes explicit configuration classes for subscribing to and publishing events via Kafka, RocketMQ, and MySQL (via JDBC). EventAppConfig defines the JDBC pool and Vertx bean, while KafkaEventConfig and RocketMQEventConfig set up the respective message listeners and producers, enabling the application to consume and produce events through these specific message queue or database backends.
samples/bank-transfer/event-consumer/src/main/java/org/enodeframework/samples/eventhandlers · high confidence
Add Kotlin-based MongoDB event store implementation
The MongoDB event store is now implemented in Kotlin, introducing new files: MongoEventStore.kt, MongoHandlers.kt, and MongoPublishedVersionStore.kt. This change adds support for batch appending events, querying aggregate events, and managing published versions in MongoDB using the Vert.x MongoDB client. The implementation handles duplicate command and event detection, retry logic, and error mapping for MongoDB write and server exceptions.
mongo · high confidence
Add MySQL event store and published version store implementations
Introduced new Kotlin implementations for the MySQL event store (MySQLEventStore) and published version store (MySQLPublishedVersionStore), along with supporting handlers (MySQLHandlers). The event store provides batch appending of domain events, querying events by aggregate ID and version range, and finding events by version or command ID. The published version store manages processor-specific version tracking with insert/update logic. These components use the Vert.x MySQL client for database interactions.
mysql · high confidence
Add NoteController for note management
Added a new REST controller at /note that exposes endpoints for creating and updating notes via the CommandBus. The controller provides create and update operations that execute commands asynchronously, returning results as reactive Mono types. A test endpoint is also included to benchmark command execution performance using different return types and execution modes.
samples/bank-transfer/command-web/src/main/java/org/enodeframework/samples/controller/note · high confidence
Add Ons message broker integration for sending and replying to messages
New Kotlin classes (OnsMessageListeners, OnsProducerHolder, OnsSendMessageService, OnsSendReplyService) implement the message queue interfaces for Alibaba Cloud Ons. This adds support for sending messages asynchronously, handling incoming messages via listeners, and sending reply messages to a configured reply topic.
ons · high confidence
Add PostgreSQL event store implementation
The PostgreSQL event store implementation is added, providing a new backend for persisting and querying domain events. The change introduces PgEventStore, PgPublishedVersionStore, and associated handlers in the pg module, enabling the framework to store and retrieve event streams and published versions using PostgreSQL.
pg · high confidence
Add Pulsar message queue support with reply queue capability
The Pulsar integration now supports sending messages and handling replies via new Kotlin-based services. Users can send messages asynchronously through PulsarProducerHolder and PulsarSendMessageService, while the new PulsarSendReplyService enables reply queue support, allowing the framework to process and send reply messages back through Pulsar.
pulsar · high confidence
Add TCP-based reply queue support for message delivery
The TCP transport layer now supports a reply queue mechanism, enabling asynchronous message delivery via a new \PointToPointEventBus\ implementation. This change introduces three new components: \TcpReplyMessageListener\ to handle incoming reply messages and route them to the command result processor, \TcpSendReplyService\ to send reply messages over TCP, and the underlying \PointToPointEventBus\ to manage TCP connections and message queuing. This allows the system to send and receive reply messages through the TCP bridge, improving reliability for distributed event bus communication.
tcp · high confidence
Add configuration for event consumer service
The event consumer sample now includes an application.properties file that configures the service on port 8004, sets up a JDBC-MySQL event store, and connects to a Kafka message queue. A logback-spring.xml file is also added to define logging behavior for the Enode framework and the application.
samples/bank-transfer/command-web/src/main/resources, samples/bank-transfer/event-consumer/src/main/resources · high confidence
Add message queue and database configuration for the bank-transfer sample
The bank-transfer sample now includes configuration classes for connecting to Kafka, RocketMQ, and a MySQL-backed JDBC event store. Users can enable these backends by setting the 'spring.enode.mq' and 'spring.enode.datasource.eventstore' properties, which wire up the necessary Spring beans for message listening and database pooling.
samples/bank-transfer/command-consumer/src/main/java/org/enodeframework/samples/commandhandles · high confidence
Add message queue configuration for Kafka and RocketMQ
The sample application now includes dedicated configuration classes for integrating with Kafka and RocketMQ message brokers. New files, KafkaConfig.java and RocketMQConfig.java, define the necessary beans for producing and consuming messages, enabling the application to route commands and replies through these specific message queue systems.
samples/bank-transfer/command-web/src/main/java/org/enodeframework/samples/controller · high confidence
Add queue and service configuration properties
A new Java class, QueueProperties, has been added to the samples domain to centralize configuration values for message queues and services. This includes connection details for a nameserver and Kafka server, as well as default producer and consumer group identifiers for multiple instances, alongside a JDBC URL for database connectivity.
samples/bank-transfer/samples-domain/src/main/java/org/enodeframework/samples · high confidence
Add reply queue support with new message handler and model
A new reply queue mechanism has been introduced, featuring a GenericReplyMessage model and a DefaultReplyMessageHandler. The handler processes incoming reply messages by deserializing them into the GenericReplyMessage model and forwarding the result to the command result processor, enabling the system to handle command execution replies from the queue.
enode/src/main/java/org/enodeframework/queue/reply · high confidence
Added NoteEventHandler for processing note domain events
A new event handler class, NoteEventHandler, has been introduced in the event-consumer module. It subscribes to note-related domain events (NoteCreated, NoteTitleChanged, and NoteTitleChanged2) and logs the denormalized data, including title, version, and timestamp. This adds a concrete implementation for handling these specific events within the sample application.
samples/bank-transfer/event-consumer/src/main/java/org/enodeframework/samples/eventhandlers/note · high confidence
Added asynchronous task and I/O helper utilities
The framework introduces new utility classes for managing asynchronous operations and I/O tasks. The new IOHelper object provides a robust mechanism for executing asynchronous actions with built-in recursive retry logic, allowing developers to specify success, failure, and context information for async tasks. Additionally, the new Task object offers static methods to await CompletableFuture results, wait on CountDownLatch, and sleep, simplifying the handling of common concurrency primitives within the framework.
enode/src/main/java/org/enodeframework/common/io · high confidence
Added bank account event handling for transfer transactions
A new event handler for bank accounts has been introduced to process various transfer-related events, including account creation, validation results, transaction preparations, and transfer lifecycle states (started, completed, canceled). This enables the system to react to and log key banking events such as insufficient balance exceptions and transaction confirmations.
samples/bank-transfer/event-consumer/src/main/java/org/enodeframework/samples/eventhandlers/bank · high confidence
Added bank transfer sample controller
A new REST controller at /bank exposes endpoints for executing bank transfer commands. The 'transfer' endpoint demonstrates creating accounts, depositing funds, and processing transfers (including invalid and insufficient-funds scenarios) using the CommandBus. The 'perf' endpoint provides a performance test that creates multiple accounts, deposits funds, and executes a high volume of transfer transactions to measure throughput.
samples/bank-transfer/command-web/src/main/java/org/enodeframework/samples/controller/bank · high confidence
Added command classes for note operations
New command classes, CreateNoteCommand and ChangeNoteTitleCommand, have been added to the samples domain. These classes extend AbstractCommandMessage and allow users to create notes and update note titles within the bank-transfer sample application.
samples/bank-transfer/samples-domain/src/main/java/org/enodeframework/samples/commands/note · medium confidence
Added command handlers for bank account, deposit, and transfer transactions
The sample application now includes command handlers for managing bank accounts, deposit transactions, and transfer transactions. Specifically, \BankAccountCommandHandler\ processes account creation, validation, and transaction preparation/commit commands. \DepositTransactionCommandHandle\ manages the lifecycle of deposit transactions, including starting, confirming preparation, and finalizing deposits. \TransferTransactionCommandHandlers\ handles the full flow of transfer transactions, including starting, confirming account validation, and processing out/in transfers and cancellations. These handlers implement the asynchronous command processing logic for the bank transfer sample.
samples/bank-transfer/command-consumer/src/main/java/org/enodeframework/samples/commandhandles/bank · high confidence
Added common extensions for messaging, ID generation, and classpath scanning
Added new components in the \org.enodeframework.common.extensions\ package: a \MessageMonitor\ interface and \NoOpMessageMonitor\ for tracking message processing results; a \SnowFlake\ class for generating unique IDs based on timestamp, datacenter, and machine identifiers; an \ObjectContainer\ interface for dependency injection resolution; a \SystemClock\ class that provides a high-performance, thread-safe current time retrieval; and a \ClassPathScanHandler\ for scanning classes in the classpath, which was also renamed from the \com.enode\ package to \org.enodeframework\. Additionally, a \SysProperties\ class was added to define system-level constants for message and command handling.
enode/src/main/java/org/enodeframework/common/extensions · high confidence
Added database schema scripts for EventStore implementations
New SQL scripts for MySQL and PostgreSQL define the 'event\_stream' and 'published\_version' tables, establishing the required unique indexes for idempotent event processing. A MongoDB script (mongo.js) also adds corresponding unique indexes. Additionally, a broker configuration file and a README explaining the EventStore setup have been added to the scripts directory.
scripts · medium confidence
Added default JSON serialization service
A new default serialization implementation has been introduced in the \org.enodeframework.common.serializing\ package. The \SerializeService\ interface defines methods for serializing objects to and from JSON strings and byte arrays, and the \DefaultSerializeService\ provides a concrete implementation using Jackson's \JsonMapper\. This change enables standard JSON serialization and deserialization for the framework's components.
enode/src/main/java/org/enodeframework/common/serializing · medium confidence
Added default handlers and publishers for application and exception messages
The framework now includes default implementations for publishing and handling application messages and domain exception messages. Specifically, it adds DefaultApplicationMessageHandler and DefaultApplicationMessagePublisher to process and send standard application messages, as well as DefaultPublishableExceptionMessageHandler and DefaultPublishableExceptionMessagePublisher to handle and send domain exception messages. These components enable the queuing system to serialize, route, and dispatch these specific message types asynchronously.
enode/src/main/java/org/enodeframework/queue/applicationmessage, enode/src/main/java/org/enodeframework/queue/publishableexceptions · high confidence
Added functional programming interfaces and delayed task support
The enode framework introduces a new set of functional interfaces in the \org.enodeframework.common.function\ package, including \Action\, \Action1\ through \Action4\, \Func\, \Func1\ through \Func3\, and a \DelayedTask\ utility for scheduling tasks with delays. These additions provide a consistent way to pass and execute code blocks and functions within the framework.
enode/src/main/java/org/enodeframework/common/function · high confidence
Added metrics monitoring for message processing and system capacity
New classes have been added to the metrics module to provide observability into message processing performance and system capacity. The \GlobalMetricRegistry\ now registers monitors for event processors, command buses, and message publishers, tracking metrics such as message latency, processing duration, and capacity utilization. Specific monitors include \EventProcessorLatencyMonitor\ for measuring processing delays, \CapacityMonitor\ for tracking resource utilization, \MessageTimerMonitor\ for timing message flows, and \MessageCountingMonitor\ for counting message states.
metrics · high confidence
Added process managers for bank transfer and deposit transactions
New process managers have been introduced to coordinate the flow of bank transactions. The \DepositTransactionProcessManager\ handles the lifecycle of deposit transactions, reacting to start, preparation, and completion events to trigger subsequent commands. Similarly, the \TransferTransactionProcessManager\ orchestrates transfer transactions, managing account validation, debit/credit preparation, and final confirmation steps. These components implement the event-driven logic for these specific banking operations within the event consumer.
samples/bank-transfer/event-consumer/src/main/java/org/enodeframework/samples/eventhandlers/bank/processmanagers · high confidence
Added utility classes for assertions and ID generation
The framework introduces new utility classes in the common package: an Assert class providing methods for validating non-null, non-empty, and boolean states, and an IdGenerator class that generates unique identifiers using a SnowFlake algorithm.
enode/src/main/java/org/enodeframework/common/utils · high confidence
Adds bank domain commands for transaction lifecycle management
The sample application now includes a comprehensive set of command classes for managing the bank transfer domain, including creating accounts, validating accounts, and initiating or confirming deposits and transfers. New commands such as AddTransactionPreparationCommand, CommitTransactionPreparationCommand, and various Confirm\* commands allow users to execute specific stages of the transaction workflow, supporting both deposit and transfer operations within the Enode framework.
samples/bank-transfer/samples-domain/src/main/java/org/enodeframework/samples/commands/bank · high confidence
Adds domain models for bank transfer and note features
Introduces new domain entities and events for the bank-transfer sample, including the BankAccount aggregate with transaction preparation and balance management, DepositTransaction and TransferTransaction aggregates with their respective state machines and events, and a simple Note aggregate. These files define the core domain logic for account validation, fund transfers, and note management within the application.
samples/bank-transfer/samples-domain/src/main/java/org/enodeframework/samples/domain · high confidence
Commanding subsystem migrated to Kotlin with new abstractions
The commanding module has been rewritten in Kotlin, introducing new abstractions for command execution and processing. This includes the \CommandBus\ interface for sending and executing commands asynchronously or synchronously, a \CommandContext\ for managing aggregate roots during command processing, and a \CommandProcessor\ to manage the lifecycle of command processing. Additionally, a \ProcessingCommandMailbox\ has been added to handle message ordering and concurrency for aggregate roots, ensuring that commands for the same aggregate are processed sequentially. The package structure has also been updated from \com.enode.commanding\ to \org.enodeframework.commanding\.
enode/src/main/java/org/enodeframework/commanding · high confidence
Introduce Kotlin-based eventing infrastructure with coroutine-backed mailboxes
The eventing subsystem has been rewritten in Kotlin, introducing a new set of core classes and interfaces for domain event handling. This includes the \DomainEventStream\ and \AbstractDomainEventMessage\ for representing and managing domain events, alongside result types like \EventAppendResult\ and \BatchAggregateEventAppendResult\ to track event append statuses. A significant behavioral change is the introduction of \EventCommittingContextMailBox\ and \ProcessingEventMailBox\, which utilize Kotlin coroutines to manage asynchronous event processing and message queues, replacing previous synchronous or non-coroutine-based implementations. The \EventCommittingService\ and \EventStore\ interfaces define the new contract for committing and storing events, supporting batch operations and async retrieval.
enode/src/main/java/org/enodeframework/eventing · high confidence
Introduce in-memory eventing implementations for the Enode framework
Added new in-memory implementations for event sourcing and processing within the Enode framework, including DefaultEventCommittingService, DefaultProcessingEventProcessor, and DefaultEventSerializer, alongside InMemoryEventStore and InMemoryPublishedVersionStore. These components enable lightweight, non-persistent event handling and version tracking, supporting features like domain event publishing, batch message processing, and coroutine-based mailbox handling for testing or scenarios where durable storage is not required.
enode/src/main/java/org/enodeframework/eventing/impl · high confidence
Introduces new queue message handling and sending interfaces in Kotlin
The queue module now includes new Kotlin-based interfaces and classes for message handling and sending. A new MessageContext interface allows for post-processing of messages, while the MessageHandler interface and its holder (MessageHandlerHolder) provide a mechanism to route and execute handlers for different message types. The QueueMessage class defines the structure for messages including body, topic, tag, routeKey, and type. Additionally, SendMessageService and SendReplyService interfaces are introduced to support asynchronous message sending and reply handling, with the latter specifically supporting ReplyMessage types.
enode/src/main/java/org/enodeframework/queue · medium confidence
Introduces queue-based command bus and result processing
The enode framework now supports asynchronous command execution via a message queue. A new 'queue/command' package provides a DefaultCommandBus that sends commands to a queue and waits for results using a DefaultCommandResultProcessor. This processor manages task completion sources, handles reply messages, and enforces a timeout to prevent memory leaks from uncompleted commands.
enode/src/main/java/org/enodeframework/queue/command · high confidence
Migrated RocketMQ integration to Kotlin with new message handling classes
The RocketMQ integration has been rewritten in Kotlin, replacing the previous Java implementation. This change introduces new classes for message listening (RocketMQMessageListener, RocketMQMessageOrderlyListener), production (RocketMQProducerHolder), and sending (RocketMQSendMessageService, RocketMQSendReplyService). The old Java classes (including RocketMQTool, SendRocketMQService, and various listener/publisher classes) have been removed.
rocketmq · high confidence
New annotations for command, event, priority, and subscribe markers
The enode framework now provides a set of new Java annotations in the org.enodeframework.annotation package: @Command, @Event, @Priority, and @Subscribe. These annotations allow developers to mark classes and methods for framework processing, such as identifying command handlers, event sources, execution priorities, and subscription points. This change introduces new API surface for building event-driven applications within the framework.
enode/src/main/java/org/enodeframework/annotation · high confidence
New command handlers for note creation and title updates
The sample application now includes dedicated command handlers for managing notes. Specifically, a new Java handler allows creating a new note, while a new Kotlin handler enables updating a note's title. These additions demonstrate how to implement command handling for these specific business operations within the Enode framework.
samples/bank-transfer/command-consumer/src/main/java/org/enodeframework/samples/commandhandles/note · high confidence
New exception classes for Enode framework
The Enode framework now provides a comprehensive set of new exception classes in the \org.enodeframework.common.exception\ package, including \AggregateRootAlreadyExistException\, \AggregateRootCreateException\, \AggregateRootInvalidException\, \AggregateRootNotFoundException\, \AggregateRootReferenceChangedException\, \AggregateRootTypeNotMatchException\, \AggregateRootTypeRepositoryNotFoundException\, \DomainEventInvalidException\, \DuplicateCommandRegisterException\, \DuplicateEventStreamException\, \EnodeClassNotFoundException\, \EnodeException\, \EnodeInterruptException\, \EventStoreException\, \HandlerNotFoundException\, \HandlerRegisterException\, \IdGenerateException\, \MailBoxInvalidException\, \MailBoxProcessException\, \MessageInstanceCreateException\, \MethodInvokeException\, \ProducerNotFoundException\, \PublishedVersionStoreException\, and \ReplyAddressInvalidException\. Additionally, the existing \IORuntimeException\ has been migrated from the \com.enode.common.io\ package to this new exception package and now extends the new \EnodeException\ base class.
enode/src/main/java/org/enodeframework/common/exception · high confidence
New messaging abstractions and handler proxies for asynchronous processing
The enode framework introduces a new messaging layer in the \org.enodeframework.messaging\ package, providing core abstractions for message handling. This includes base classes for application and reply messages, along with interfaces for message dispatching, publishing, and handler registration. Specifically, it adds \Message\ and \ReplyMessage\ interfaces, abstract message classes, and proxy interfaces (\MessageHandlerProxy1\, \2\, \3\) that support asynchronous handling of one, two, or three messages respectively. These components enable the framework to route and process messages asynchronously via \MessageDispatcher\ and \MessagePublisher\ interfaces, supporting a more flexible and scalable messaging architecture.
enode/src/main/java/org/enodeframework/messaging · high confidence
Spring Boot auto-configuration for Enode framework
The Spring module now provides comprehensive auto-configuration for the Enode framework, enabling zero-configuration setup for various event stores (In-Memory, MySQL, PostgreSQL, MongoDB) and message queues (Kafka, AMQP, Pulsar, Ons). The \@EnableEnode\ annotation triggers the import of \EnodeConfigurationSelector\, which wires up core components like \DefaultCommandOptions\, \DefaultEventStoreOptions\, and specific store implementations (e.g., \JDBCEventStore\, \MongoEventStore\). This allows users to enable Enode functionality in a Spring Boot application simply by adding the dependency and using the \@EnableEnode\ annotation, with behavior determined by properties like \spring.enode.mq\ and \spring.enode.eventstore\.
spring · high confidence
Removals
Removal of command and event sample implementations
The command and event sample implementations for the bank and note domains have been removed. This includes all command handlers (e.g., CreateAccountCommandHandler, StartDepositTransactionCommandHandler), event handlers (e.g., AccountCreatedEventHandler, TransferTransactionCompletedEventHandler), and process managers (e.g., AbstractDepositTransactionProcessManager) from the command-consumer and event-consumer samples. Configuration files (application.yml, log4j2.xml) and application entry points (Application.java) for these samples have also been deleted.
samples/command-consumer, samples/event-consumer · high confidence
Removal of core command processing and infrastructure components
The enode module has removed a large set of core command processing classes, including the \ENodeAutoConfiguration\, \ENodeBootstrap\, and \InMemoryConfiguration\ setup classes, as well as the entire \commanding\ package containing command interfaces, handlers, and implementations. This change eliminates the built-in command execution, message routing, and in-memory event storage capabilities from the framework.
enode/src/main/java/com · high confidence
Removed bank and note sample implementations
The \samples/command-sender\ and \samples/domain\ directories have been deleted, removing the entire bank and note sample implementations. This includes all related command classes (e.g., \CreateAccountCommand\, \StartTransferTransactionCommand\), domain models (e.g., \BankAccount\, \DepositTransaction\), event classes, and configuration files (e.g., \application.yml\, \log4j2.xml\).
samples/command-sender, samples/domain · high confidence
Behavioural changes
AMQP message handling migrated to Kotlin with async support
The AMQP module has been rewritten in Kotlin, introducing new services for sending messages and replies asynchronously. AmqpMessageListeners now handle incoming messages and batches, supporting both standard and channel-aware processing. AmqpProducer and AmqpSendMessageService provide async sending capabilities, while AmqpSendReplyService enables reply message support. The implementation leverages Spring AMQP's reactive template for non-blocking operations.
amqp · high confidence
Configure Enode framework with JDBC, Kafka, and logging for the bank-transfer consumer
The bank-transfer command-consumer sample now includes explicit configuration for the Enode framework, specifying a MySQL JDBC event store and Kafka message queue with dedicated topics for commands, events, and replies. Additionally, a Logback logging configuration is added to capture Enode framework logs at the DEBUG level, with file and console appenders configured for application and console output.
samples/bank-transfer/command-consumer/src/main/resources · high confidence
Domain layer refactored to Kotlin with new interfaces and base classes
The domain layer has been refactored, moving from Java to Kotlin and introducing new abstractions for aggregate management. This includes the new AbstractAggregateRoot base class and the AggregateRoot interface, alongside updated interfaces for repositories (AggregateRepository, Repository), storage (AggregateStorage, AggregateSnapshotter), and caching (MemoryCache). The change also migrates the package structure from com.enode to org.enodeframework.domain and renames several components, such as IAggregateRepositoryProvider becoming AggregateRepositoryProvider, to align with the new architecture.
enode/src/main/java/org/enodeframework/domain · high confidence
Introduces Kotlin-based domain implementation classes
The domain layer's implementation classes in \enode/src/main/java/org/enodeframework/domain/impl\ have been rewritten in Kotlin. This includes new implementations for aggregate repository management (\DefaultAggregateRepositoryProvider\, \DefaultAggregateRepositoryProxy\), aggregate root creation (\DefaultAggregateRootFactory\), internal event handling (\DefaultAggregateRootInternalHandlerProvider\), snapshotting (\DefaultAggregateSnapshotter\), memory caching (\DefaultMemoryCache\), repository access (\DefaultRepository\), and event sourcing storage (\EventSourcingAggregateStorage\, \SnapshotOnlyAggregateStorage\).
enode/src/main/java/org/enodeframework/domain/impl · high confidence
Kafka integration rewritten in Kotlin with new message handling architecture
The Kafka integration has been completely rewritten in Kotlin, replacing the previous Java implementation. This change introduces new classes for message listeners (KafkaMessageListeners), a producer holder (KafkaProducerHolder), and dedicated services for sending messages (KafkaSendMessageService) and replies (KafkaSendReplyService). The old Java-based consumers, publishers, and utility classes have been removed.
kafka · high confidence
Message dispatching rewritten in Kotlin with coroutine support
The message dispatching implementation in the enode framework has been rewritten in Kotlin, introducing native support for Kotlin suspend functions and reactive types (Mono/Flux/CompletionStage). The new DefaultMessageDispatcher and its supporting classes (DefaultMessageHandlerProxy1/2/3, etc.) handle message routing and handler invocation using Kotlin coroutines, allowing handlers to be defined as suspend functions or return reactive streams, improving integration with modern asynchronous programming models.
enode/src/main/java/org/enodeframework/messaging/impl · high confidence
Migrate commanding implementation to Kotlin with coroutine support
The command processing and execution components in the \enodeframework.commanding.impl\ package have been rewritten in Kotlin. This change introduces support for Kotlin coroutines, allowing command handlers to be defined as suspend functions. The \DefaultCommandHandlerProxy\ now detects and invokes suspend methods, while \DefaultCommandProcessor\ and \DefaultProcessingCommandHandler\ utilize coroutine dispatchers and async/await patterns for asynchronous command execution and mailbox management.
enode/src/main/java/org/enodeframework/commanding/impl · high confidence
Migrate domain event queue handling to Kotlin
The domain event queue implementation has been rewritten in Kotlin, introducing new classes for handling and publishing domain events. DefaultDomainEventMessageHandler now processes incoming queue messages, deserializes them into a DomainEventStream, and processes them via the event processor. DefaultDomainEventPublisher converts outgoing DomainEventStream objects into queue messages for publishing. Additionally, new message types DomainEventHandledMessage and GenericDomainEventMessage are introduced to support event handling and serialization in the queue system.
enode/src/main/java/org/enodeframework/queue/domainevent · medium confidence
Redis message handling migrated to Kotlin
The Redis integration for message handling has been rewritten in Kotlin. This introduces \RedisReplyMessageListener\ to process incoming Redis messages and route them to the appropriate message handler, and \RedisSendReplyService\ to asynchronously send reply messages via Redis. These changes replace the previous implementation, affecting how the application communicates with Redis for queue and reply messaging.
redis · high confidence
Refactor infrastructure layer to Kotlin and introduce new core interfaces
The infrastructure package has been migrated to Kotlin, introducing new core interfaces such as AssemblyInitializer, MethodInvocation, ObjectProxy, and TypeNameProvider. A new AbstractHandlerProvider base class manages handler registration and priority, while supporting Kotlin suspend methods. Additionally, utility classes like TypeUtils and ManyType are added to support type resolution and generic type handling.
enode/src/main/java/org/enodeframework/infrastructure · medium confidence
Refactored scheduling and worker components with modern Java practices
The scheduling subsystem was refactored to modernize the codebase: the \ScheduleService\ interface and \DefaultScheduleService\ implementation were moved to the \org.enodeframework\ package, replacing the legacy \com.enode\ package. The \ScheduleService\ class was renamed to \DefaultScheduleService\ and updated to use \java.util.concurrent\ types (e.g., \ScheduledFuture\<?\>\) and \slf4j\ logging. The \Worker\ class was similarly moved to the new package, updated to use \slf4j\ logging, and had its \actionName\ field and related accessor methods removed. These changes improve code consistency and logging standards within the scheduling module.
enode/src/main/java/org/enodeframework/common/scheduling · high confidence
Removed MySQL-specific database schema scripts
The MySQL-specific table generation SQL scripts have been removed from the repository. This change eliminates the hardcoded MySQL database schema definitions, aligning with the project's shift to support multiple event store backends (such as MongoDB, TiDB, and PostgreSQL) rather than being tied to a single database implementation.
enode/scripts · high confidence
Test coverage
Added comprehensive test suite for Enode framework core and message publishing; Added test configuration for event store and message queue backends.
Dependencies
Maven build system restructured with new module layout and dependency management
The project's Maven build structure has been significantly reorganized. The root artifact and parent POM have been migrated from \com.enode:enode-java:1.0.0\ to \org.enodeframework:enode-parent\ using a \${revision}\ property. A new Bill of Materials (BOM) module (\enode-dependencies-bom\) has been introduced to centralize dependency management for all sub-modules. Several existing sample modules (\command-consumer\, \event-consumer\, \command-sender\, \domain\) were removed and replaced with a new \bank-transfer\ sample. Additionally, new modules for JDBC, MySQL, PostgreSQL, MongoDB, AMQP, TCP, and Metrics have been added to the build, each with their own \pom.xml\ files defining their specific dependencies.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 50 → 50 (+0.6)
- Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 97 → 98 (+0.3)
- Architecture 100 → 97 (-3.1)
- Maturity 57 → 57 (+0.0)
- Readiness 22 → 26 (+4.0)
- Security 87 → 79 (-7.6)
Resolved (32)
- Change coupling: EnodeOnsAutoConfig.java ↔ EnodeRocketMQAutoConfig.java (spring/src/main/java/org/enodeframework/spring/EnodeOnsAutoConfig.java)
- Change coupling: JDBCEventStore.kt ↔ JDBCPublishedVersionStore.kt (jdbc/src/main/java/org/enodeframework/jdbc/JDBCEventStore.kt)
- Coverage not included — suite not readable by the collector
- Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
- Duplicated block (10 lines × 2) (enode/src/main/java/org/enodeframework/commanding/impl/DefaultCommandHandlerProvider.kt)
- Duplicated block (10 lines × 2) (enode/src/main/java/org/enodeframework/messaging/impl/DefaultThreeMessageHandlerProvider.kt)
- Duplicated block (10 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (10 lines × 3) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (10 lines × 4) (enode/src/main/java/org/enodeframework/messaging/impl/DefaultThreeMessageHandlerProvider.kt)
- Duplicated block (11 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (12 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCEventStore.kt)
- Duplicated block (13 lines × 2) (enode/src/main/java/org/enodeframework/eventing/impl/DefaultEventCommittingService.kt)
- Duplicated block (7 lines × 2) (enode/src/main/java/org/enodeframework/commanding/impl/DefaultProcessingCommandHandler.kt)
- Duplicated block (7 lines × 2) (mongo/src/main/java/org/enodeframework/mongo/MongoEventStore.kt)
- Duplicated block (8 lines × 2) (amqp/src/main/java/org/enodeframework/amqp/message/AmqpMessageListeners.kt)
- Duplicated block (8 lines × 2) (enode/src/main/java/org/enodeframework/eventing/ProcessingEventMailBox.kt)
- Duplicated block (8 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCPublishedVersionStore.kt)
- Duplicated block (8 lines × 2) (mongo/src/main/java/org/enodeframework/mongo/MongoEventStore.kt)
- Duplicated block (8 lines × 2) (mongo/src/main/java/org/enodeframework/mongo/MongoHandlers.kt)
- Duplicated block (8 lines × 2) (rocketmq/src/main/java/org/enodeframework/rocketmq/message/RocketMQMessageListener.kt)
- …and 12 more
New (51)
- ClassPathScanHandler.doScanPackageClassesByJar (cognitive 20) (enode/src/main/java/org/enodeframework/common/extensions/ClassPathScanHandler.java)
- Dependency hygiene PARTLY measured — Maven/Gradle declarations read, no dependency graph resolved
- Documentation: no installation or build instructions (README.md)
- Documentation: written for insiders (docs/intro.md)
- Duplicated block (10 lines × 2) (enode/src/main/java/org/enodeframework/commanding/ProcessingCommandMailbox.kt)
- Duplicated block (10 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (10–14 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (12 lines × 2) (enode/src/main/java/org/enodeframework/commanding/impl/DefaultCommandHandlerProvider.kt)
- Duplicated block (12 lines × 2) (enode/src/main/java/org/enodeframework/eventing/impl/DefaultEventCommittingService.kt)
- Duplicated block (13 lines × 2) (mongo/src/main/java/org/enodeframework/mongo/MongoEventStore.kt)
- Duplicated block (13 lines × 3) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (15 lines × 2) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCEventStore.kt)
- Duplicated block (15–18 lines × 4) (enode/src/main/java/org/enodeframework/messaging/impl/DefaultThreeMessageHandlerProvider.kt)
- Duplicated block (17 lines × 3) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCEventStore.kt)
- Duplicated block (17–18 lines × 3) (jdbc/src/main/java/org/enodeframework/jdbc/JDBCHandlers.kt)
- Duplicated block (21 lines × 2) (enode/src/main/java/org/enodeframework/messaging/impl/DefaultThreeMessageHandlerProvider.kt)
- Duplicated block (6 lines × 2) (enode/src/main/java/org/enodeframework/commanding/impl/DefaultProcessingCommandHandler.kt)
- Duplicated block (6 lines × 2) (mongo/src/main/java/org/enodeframework/mongo/MongoEventStore.kt)
- Duplicated block (7 lines × 2) (amqp/src/main/java/org/enodeframework/amqp/message/AmqpMessageListeners.kt)
- Duplicated block (7 lines × 2) (enode/src/main/java/org/enodeframework/eventing/ProcessingEventMailBox.kt)
- …and 31 more
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
itswuanran/enode was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 22 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 06bee95b1ba2335fdad0174f871b667749281d00 — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-821afab8930d.