Kai Moritz [Thu, 22 Feb 2024 15:03:08 +0000 (16:03 +0100)]
fix: GREEN - Fixed the restore-mechanism
* The code of a reactive flow _must not_ call blocking functions.
* In order to solve this, the restore-process is triggered explicitly
after the creation of the classes.
Kai Moritz [Tue, 20 Feb 2024 15:12:00 +0000 (16:12 +0100)]
refactor: RED - Refined success/error-handling for restore-operations
* This innocent little change discloses a severe missconception in the
implementation of the storage strategies.
* The call to `Mono.block()`, though not really changing the behaviour
during the restore-process, triggers a sanity-check from
io.projectractor.
Kai Moritz [Tue, 20 Feb 2024 10:28:22 +0000 (11:28 +0100)]
refactor: Refined stream-definition in `StorageStrategy#write`
* Changed the stream-definition to a more natural order.
* As a result, the stored `ChatRoomInfo`-instances do not have to be
handed clumsily to the following stream.
Kai Moritz [Tue, 20 Feb 2024 06:47:22 +0000 (07:47 +0100)]
refactor: Simplified `StorageStrategy`
* Reconfigurable success/error-logging was introduced for
`NoStorageStorageStrategy`.
* But as it turns out, this strategy can simply apply its logging in the
overwritten method, that disables the whole storing-logic.
* Hence, the interface was greatly simplified again, by removing this
ununsed mechanism.
Kai Moritz [Mon, 19 Feb 2024 14:01:58 +0000 (15:01 +0100)]
refactor: Moved extracted the `subscribe()`-call from `StorageStrategy`
* The subscription does no more happen inside the implementations of the
interface `StorageStrategy`.
* Instead, the methods, that are defined in `StorageStrategy` return the
created `Flux`.
* The call to `subscribe()` happens in the code, that uses this methods.
* This faciliates feature refinements concerning the asynchronous handling
of success- and error-cases and so forth.
Kai Moritz [Sun, 18 Feb 2024 19:12:19 +0000 (20:12 +0100)]
fix: Without `@DirtiesContext` the app is not teared down correctly
* `StorageStrategy` depends on Spring to call the method
`ChatBackendApplication#onExit()`, that is annotated with `@PreDestroy`.
* If this method is not called, the strategy is not applied, which leads
to errors in the integration-tests.
* This happens, if all tests are run through Maven, because Spring
recycles the application-context and only tears down the context after
all tests have run.
* The addition of `@DirtiesContext` on those tests forces Spring to tear
down the application completely after each so annotated test.
* Hence, the method is called as expected, which fixes the described
errors.
Kai Moritz [Sat, 3 Feb 2024 16:25:45 +0000 (17:25 +0100)]
fix: `getChatRoomInfo()` thrwos `LoadInProgressException` when loading
- The method `InfoChannel.getChatRoomInfo(UUID)` has to check, if loading
is in process.
- Otherwise, an existing chat-room might erronously not be found, if it is
requested, while `InfoChannel` is loading, because it is not yet loaded.
Kai Moritz [Sun, 24 Sep 2023 19:39:01 +0000 (21:39 +0200)]
fix: The actual position has to be requested from the consumer
* If the last seen offset and the current offset differ, although the
partition did not contain any messages between this offsets, the loading
process got stuck, because the position never advanced.
* Therefore, the actual position, that is compared against the read
end-offset, has to be requested from the consumer.
* Implemented a first simple `ShardingPublisherStrategy`, that uses the
https://www.haproxy.com/documentation/haproxy-runtime-api/[HAProxy Runntime API]
to publish changed ownerships.
* Added configuration-properties `kafka.haproxyRuntimeApi` and
`kafka.haproxyMap` to configure the strategy.
* The interface is used by `DataChannel` to publish the changed ownership
each time, a new partition is assigned to the consumer-group.
* Added a dummy-implementation in `KafkaServicesConfiguration`.
Kai Moritz [Sat, 16 Sep 2023 19:40:45 +0000 (21:40 +0200)]
feat: Introduced events that are send, if a shard is assigned/revoked
* In order to redirect requests to the appropriate instances, each
instance must know the mapping from shard-IDs to instance-URIs.
** For the static `in-memory`-implementation `ShardedChatHomeService`,
this is a static mapping, that can be configured and read on start-up.
** For the dynamic `KafkaChatHomeService`, this mapping has to be
propageted to all instances each time the partition-assignment of the
consumer-group changes.
* Changes for `ShardedChatHomeService`
** Introduced `ChatBackendProperties.shardOwners` (of type `URI[]`).
** Each instance reads the static mapping from shard-ID to instance-URI
on start-up.
* Changes for `KafkaChatHomeService`
** Introduced `KafkaServicesProperties.instanceUri` (of type `URI`).
** Each instance reads its URI on start-up.
** `DataChannel` sends an event for each assigned/removed partition,
when the partition-assignment of the consumer-group changes.
** These events propagete the changed mapping from partition-ID to
instance-URI.
** `InfoChannel` receives these events and updates the dynamic mapping
from partition-ID (aka:shard-ID) to instance-URI.
* The shards, that are owned by an instance, can be queried via `/shards`.
Kai Moritz [Tue, 12 Sep 2023 21:33:59 +0000 (23:33 +0200)]
refactor: Separated channels for data and info -- Refactored/aligned code
* Split `ChatRoomChannel` into `InfoChannel` and `DataChannel`
** `DataChannel` manages only data for chat-messages
** `InfoChannel` manages all info-data (at the moment only
`EventChatRoomCreated`)
* Aligned test-setup for kafka-related tests
Kai Moritz [Mon, 11 Sep 2023 16:36:05 +0000 (18:36 +0200)]
refactor: Separated channels for data and info -- Moved/copied classes
* Split `ChatRoomChannel` into `InfoChannel` and `DataChannel`
** `DataChannel` manages only data for chat-messages
** `InfoChannel` manages all info-data (at the moment only
`EventChatRoomCreated`)
* Aligned test-setup for kafka-related tests
* Moved startup-logic in a separate class (`ConsumerTaskExecutor`), so
that it is reusable more easily in test scenarios.
* `KafkaServicesApplicationRunner` is instanciated via `@Component`, so
that it is _not_ instanciated automatically, if the configuration is
triggered explicitly via `KafkaServicesConfiguration` in test scenarios.
* Moved method `ChatRoomFactory.createChatRoom(UUID, String)` to `ChatHome`.
* Allowed `null`-values for `ChatRoom.shard`.
* Moved logic from `InMemoryChatHomeService` into `SimpleChatHome` respective
`ShardedChatHome` and removed obsolete class.
* Adapted the configuration of the tests to the model changes:
Kai Moritz [Fri, 18 Aug 2023 12:09:02 +0000 (14:09 +0200)]
fix: GREEN - Fixed NPE in `ShardedChatHome.getChatRoom()` for foreign shard
* `ShardedChatHome.getChatRoom(UUID)` know checks, if a `ChatHome` exists
for the selected shard.
* If no `ChatHome` exists, a `ShardNotOwnedException` is thrown.
* The `ChatBackendControllerAdvice` translates the exception to an error
of type 404 - NOT FOUND, to fullfill the defined expectations.
Kai Moritz [Sat, 18 Feb 2023 10:07:21 +0000 (11:07 +0100)]
test: RED - Proofed existence of an NPE in `ShardedChatHome.getChatRoom()`
- Refined `AbstractConfigurationIT` to show, that an NPE can occure in
`ShardedChatHome.getChatRoom()`.
- Defined the expected behaviour, if the NPE is handled correctly in the
refined integration-test.
Kai Moritz [Sat, 19 Aug 2023 15:33:03 +0000 (17:33 +0200)]
feat: Implemented new Default-`StorageStrategy` `none'
* If `none` is selected as storage strategy, an empty implementation of
`Storage-Strategy` instanciated.
* The owned shardes are derived from the according configuration property.
* Before, they were derived from the stored data.
Kai Moritz [Sun, 26 Feb 2023 14:30:20 +0000 (15:30 +0100)]
refactor: `ChatRoomFactory` returns real `ChatRoom`s
- `ChatHomeService` only deals with real `ChatRoom`s.
- Hence, there is no need for `ChatRoomFactory`, to return the simplified
interface `ChatRoomInfo`.
- This is, because the implementation specific logic is implemented in the
`ChatHomeService`, not `ChatHome` itself: the actual implementation is
hidden behind that service (and behind the service `ChatRoomService` in
the domain-class `ChatRoom`).