Kai Moritz [Sat, 3 Feb 2024 21:44:02 +0000 (22:44 +0100)]
refactor: Added success- and failure-callbacks to `StorageStrategy`
Kai Moritz [Sat, 3 Feb 2024 19:43:29 +0000 (20:43 +0100)]
refactor: `KafkaServicesApplicationRunner` aufgeräumt
Kai Moritz [Sat, 3 Feb 2024 11:08:15 +0000 (12:08 +0100)]
fix: Config-ITs do not fail, if run multiple times
Kai Moritz [Sat, 3 Feb 2024 07:35:38 +0000 (08:35 +0100)]
fix: Removed manual version-management for testcontainers.org
Kai Moritz [Sat, 3 Feb 2024 07:32:40 +0000 (08:32 +0100)]
feat: Upgraded Spring Boot 3.1.3 -> 3.2.2
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 [Sat, 3 Feb 2024 14:32:25 +0000 (15:32 +0100)]
refactor: compute `loadInProgress` on offset-change
Kai Moritz [Sat, 3 Feb 2024 14:20:25 +0000 (15:20 +0100)]
refactor: separated message- and record- (aka offset-) handling
Kai Moritz [Sat, 3 Feb 2024 14:13:09 +0000 (15:13 +0100)]
refactor: Renamed method in `InfoChannel` according to conventions
Kai Moritz [Sat, 3 Feb 2024 14:11:50 +0000 (15:11 +0100)]
refactor: Made only locally used method in `KafkaChatHomeService` private
Kai Moritz [Sun, 24 Sep 2023 19:42:22 +0000 (21:42 +0200)]
feat: The position of the last seen messages is stored on a revoke
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.
Kai Moritz [Sun, 24 Sep 2023 19:38:46 +0000 (21:38 +0200)]
refactor: Added logging of loaded messages
Kai Moritz [Tue, 20 Feb 2024 09:26:25 +0000 (10:26 +0100)]
refactor: Refined success/error-handling when publishing shard-ownership
Kai Moritz [Sun, 17 Sep 2023 09:31:22 +0000 (11:31 +0200)]
feat: Implemented `HaproxyShardingPublisherStrategy`
* 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.
Kai Moritz [Tue, 20 Feb 2024 08:53:10 +0000 (09:53 +0100)]
feat: Introduced interface `ShardingPublisherStrategy`
* 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 [Tue, 20 Feb 2024 08:48:03 +0000 (09:48 +0100)]
feat: Introduced a configurable instance-id
Kai Moritz [Fri, 22 Sep 2023 16:20:31 +0000 (18:20 +0200)]
fix: `ConsumerTaskRunner` waits until the data-loading is finished
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 [Sun, 28 Jan 2024 17:50:33 +0000 (18:50 +0100)]
fix: `metadata` is never `null`
Kai Moritz [Fri, 15 Sep 2023 19:35:17 +0000 (21:35 +0200)]
refactor: DRY for computation of new `ChatRoomData` instances
Kai Moritz [Fri, 15 Sep 2023 18:56:14 +0000 (20:56 +0200)]
fix: GREEN - `DataChannel` creates entries for existent chat-rooms
Kai Moritz [Fri, 15 Sep 2023 18:04:01 +0000 (20:04 +0200)]
test: RED - Putting a message in a newly created chat-room
Kai Moritz [Fri, 15 Sep 2023 15:29:05 +0000 (17:29 +0200)]
refactor: Splitted test in `AbstractConfigurationIT` into smaler pieces
Kai Moritz [Fri, 15 Sep 2023 15:08:33 +0000 (17:08 +0200)]
refactor: Moved common test-code into helper-class `KafkaTestUtils` - ALIGN
Kai Moritz [Fri, 15 Sep 2023 08:57:55 +0000 (10:57 +0200)]
refactor: Moved common test-code into helper-class `KafkaTestUtils` - COPY
Kai Moritz [Fri, 15 Sep 2023 08:48:28 +0000 (10:48 +0200)]
refactor: Extracted interface `WorkAssignor` into separate file
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
Kai Moritz [Thu, 14 Sep 2023 21:42:59 +0000 (23:42 +0200)]
refactor: Introduced `ConsumerTaskExecutor` -- Aligned code
* 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.
Kai Moritz [Thu, 14 Sep 2023 21:41:46 +0000 (23:41 +0200)]
refactor: Introduced `ConsumerTaskExecutor` -- Copied class
Kai Moritz [Thu, 14 Sep 2023 21:17:48 +0000 (23:17 +0200)]
refactor: `KafkaChatHomeServiceTest` reuses regular startup-logic
Kai Moritz [Wed, 13 Sep 2023 19:20:39 +0000 (21:20 +0200)]
refactor: `KafkaServicesApplicationRunner` without autowireing
Kai Moritz [Mon, 11 Sep 2023 14:19:22 +0000 (16:19 +0200)]
refactor: Renamed `ChatRoomService` into `ChatMessageService` -- ALIGNE
Kai Moritz [Mon, 11 Sep 2023 14:18:42 +0000 (16:18 +0200)]
refactor: Renamed `ChatRoomService` into `ChatMessageService` -- MOVE
Kai Moritz [Mon, 11 Sep 2023 14:10:22 +0000 (16:10 +0200)]
refactor: Removed unused methods
Kai Moritz [Wed, 6 Sep 2023 21:48:50 +0000 (23:48 +0200)]
refactor: Renamed `persistence` into `implementation` - Aligned code
Kai Moritz [Wed, 6 Sep 2023 21:48:39 +0000 (23:48 +0200)]
refactor: Renamed `persistence` into `implementation` - Moved classes
Kai Moritz [Wed, 6 Sep 2023 21:46:36 +0000 (23:46 +0200)]
refactor: `storage` is not a sub-package of `persistence` - Aligned code
Kai Moritz [Wed, 6 Sep 2023 21:46:29 +0000 (23:46 +0200)]
refactor: `storage` is not a sub-package of `persistence` - Moved classes
Kai Moritz [Wed, 6 Sep 2023 21:41:37 +0000 (23:41 +0200)]
refactor: `ChatHome` is a service - Aligned code
Kai Moritz [Wed, 6 Sep 2023 21:41:27 +0000 (23:41 +0200)]
refactor: `ChatHome` is a service - Moved classes
Kai Moritz [Wed, 6 Sep 2023 21:38:28 +0000 (23:38 +0200)]
refactor: Moved exceptions into package `exceptions` - Aligned Code
Kai Moritz [Wed, 6 Sep 2023 21:38:15 +0000 (23:38 +0200)]
refactor: Moved exceptions into package `exceptions` - Moved classes
Kai Moritz [Wed, 6 Sep 2023 21:36:06 +0000 (23:36 +0200)]
refactor: Moved `ShardingStrategy` into package `persistence` -- ALIGNE
Kai Moritz [Wed, 6 Sep 2023 21:35:35 +0000 (23:35 +0200)]
refactor: Moved `ShardingStrategy` into package `persistence` -- MOVE
Kai Moritz [Sun, 3 Sep 2023 17:54:46 +0000 (19:54 +0200)]
refactor: Splitted `ChatRoomInfo` and `ChatRoomData` - Aligned Code
Kai Moritz [Sun, 3 Sep 2023 17:49:59 +0000 (19:49 +0200)]
refactor: Splitted `ChatRoomInfo` and `ChatRoomData` - Moved classes
Kai Moritz [Tue, 5 Sep 2023 22:02:28 +0000 (00:02 +0200)]
test: Refactored test-code
Kai Moritz [Sat, 2 Sep 2023 17:16:26 +0000 (19:16 +0200)]
refactor: Simplified implementation - Removed interface `ChatRoomFactory`
* 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 [Thu, 24 Aug 2023 17:24:54 +0000 (19:24 +0200)]
feat: Upgraded Spring Boot 3.0.1 -> 3.1.3
Kai Moritz [Tue, 29 Aug 2023 17:36:15 +0000 (19:36 +0200)]
refactor: `ShardNotOwnedException` should be send over `Mono.send()`
Kai Moritz [Tue, 22 Aug 2023 15:33:36 +0000 (17:33 +0200)]
test: Added tests for a chat-home _with_ shards
Kai Moritz [Tue, 22 Aug 2023 15:33:36 +0000 (17:33 +0200)]
test: Added tests for a chat-home (without shards)
Kai Moritz [Tue, 29 Aug 2023 18:33:37 +0000 (20:33 +0200)]
LoadInProgressException - ALIGN
Kai Moritz [Tue, 29 Aug 2023 18:33:15 +0000 (20:33 +0200)]
LoadInProgressException - MOVE
Kai Moritz [Tue, 22 Aug 2023 15:33:36 +0000 (17:33 +0200)]
test: Simplified `ChatBackendControllerTest`
Kai Moritz [Mon, 21 Aug 2023 16:26:53 +0000 (18:26 +0200)]
feat: `UnknownChatroomException` records shard and owned shards
Kai Moritz [Sun, 20 Aug 2023 10:20:55 +0000 (12:20 +0200)]
fix: GREEN - Correct handling of unknown chat-rooms in the Kafka-version
Kai Moritz [Sat, 2 Sep 2023 08:35:39 +0000 (10:35 +0200)]
test: RED - Added a test for a put to a non-existent chat-room
Kai Moritz [Sun, 22 Jan 2023 17:13:40 +0000 (18:13 +0100)]
feat: first runnable implementation, that is based on Kafka
Kai Moritz [Mon, 21 Aug 2023 16:25:20 +0000 (18:25 +0200)]
refactor: Removed Interface `ChatHomeService`
Kai Moritz [Sun, 20 Aug 2023 10:57:41 +0000 (12:57 +0200)]
refactor: Moved implementation details out of `domain` -- Aligned code
Kai Moritz [Sun, 20 Aug 2023 10:57:26 +0000 (12:57 +0200)]
refactor: Moved implementation details out of `domain` -- Moved classes
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`).
Kai Moritz [Fri, 17 Feb 2023 23:21:50 +0000 (00:21 +0100)]
refactor: Refined the creation of new `ChatRoom`s
- Dropped `ChatHomeService.putChatRoom(ChatRoom)`.
- `ChatRoomFactory.create(UUID, String)` returns `ChatRoomInfo`.
Kai Moritz [Fri, 17 Feb 2023 23:10:03 +0000 (00:10 +0100)]
refactor: DRY for the configuration of the `AbstractStorageStrategyIT`
Kai Moritz [Fri, 17 Feb 2023 22:34:55 +0000 (23:34 +0100)]
refactor: Refined the configuration of `AbstractStorageStrategyIT'
Kai Moritz [Tue, 24 Jan 2023 18:05:18 +0000 (19:05 +0100)]
refactor: `ChatRoomService.persistMessage(..)` returns a `Mono<Message>`
Kai Moritz [Wed, 25 Jan 2023 21:08:11 +0000 (22:08 +0100)]
refactor: Simplified the handling of `MessageMutationException`
Kai Moritz [Sun, 22 Jan 2023 17:34:21 +0000 (18:34 +0100)]
test: Added a test that assers disjunct chatrooms
Kai Moritz [Sun, 15 Jan 2023 18:48:34 +0000 (19:48 +0100)]
chore: Added a Docker-Build
Kai Moritz [Sat, 14 Jan 2023 18:53:16 +0000 (19:53 +0100)]
feat: Reintroduced `ChatRoom.shard`, becaus it is needed as a routing-hint
- Technically, the attribute is not needed.
- But, to implement the gua/sha-pattern, it is needed as routing-hing.
- Hence, it is reintroduced here and also added to the `ChatRoomTo` to
be send to the client.
Kai Moritz [Sat, 14 Jan 2023 17:09:46 +0000 (18:09 +0100)]
fix: Fixed a NPE in `ShardedChatHome.getChatRooms()`
- When collecting the `ChatRoom`s for all shards, unused shards with a
`null` value were not skipped.
- Also added log-messages of level `INFO` for the creation of `ChatRoom`,
`SimpleChatHome` and `ShardedChatHome`.
Kai Moritz [Sat, 14 Jan 2023 17:11:56 +0000 (18:11 +0100)]
fix: Removed unnecessary generic in `ChatHomeService`
Kai Moritz [Sat, 14 Jan 2023 16:40:21 +0000 (17:40 +0100)]
chore: Switched the default-configuration to sharding `none`
Kai Moritz [Sat, 14 Jan 2023 16:33:02 +0000 (17:33 +0100)]
refactor: A `ChatRoom` does not have to remember its shard any more
- The shard of a `ChatRoom` can be derived from its ID, if the configured
`ShardingStrategy` is known.
- Because the `ShardingStrategy` is known everywhere, where the shard of a
`ChatRoom` is needed, it always can be derived dynamically.
Kai Moritz [Sat, 14 Jan 2023 15:47:04 +0000 (16:47 +0100)]
refactor: Pulled business-logic into class `ShardedChatHome`
- Pulled the logic that selects the appropriate shard from the class
`ChatBackendController` into the newly introduced class
`ShardedChatHome`.
- Simplified the configuration
- `InMemoryServicesConfiguration` creates a `ChatHome` of type
`SimpleChatHome`, if the `sharding-strategy` `none` is choosen.
- In that case, the values for `num-shards` and `owned-shards` are
ignored and set to `1` and `0`.
- If the `sharding-strategy` is set to `kafkalike`, a `ChatHome` of
type `ShardedChatHome` is instanciated and the configuration
respects the configured sharding.
- Simplified the configuration of `ChatBackendControllerTest` accordingly.
Kai Moritz [Sat, 14 Jan 2023 15:07:04 +0000 (16:07 +0100)]
refactor: Made `SimpleChatHome` an implementation of `ChatHome`
Kai Moritz [Sat, 14 Jan 2023 15:01:55 +0000 (16:01 +0100)]
refactor: Removed `ChatHomeFactory`
- `ChatHomeFactory` was only used during initialization.
- By moving the instanciation of `chatHomes` into the implementation-
specific configuration, the necessity of the factory vanished.
Kai Moritz [Fri, 13 Jan 2023 23:05:31 +0000 (00:05 +0100)]
feat: Introduced a kafka-like `ShardingStrategy` for `inmemory`
- Introduced the `ShardingStrategy`, that picks a shard for a given
`ChatRoom`-ID.
- Implemented a `KafkaLikeShardingStrategy`, that reuses the hashing
algorithm, that is implementd in `Utils.murmur2()` in the
`org.apache.kafka:kafka-clients` library.
- The attribute `shard` of the `ChatHome` has to be restored according
to the configured `ShardingStrategy` when loading the state - it must
not be safed with the stored data, because it might change due to
configuration-changes.
- The `ChatBackendController` was not configured correctly, because it
had consumed the single `ChatHome` from the old configuration as the
only entry in its `ChatHome[]`-array.
- Refined the application-properties: Introduced an inner subclass
`InMemoryServicesProperties` of `ChatBackendProperties`, that
encapsulates the properties, that only concern the implementation
`inmemory`.
- Added the configuration-parameters `numShards` and `ownedShards`,
that are needed by `inmemory`, to handle the sharding correctly.
- Introduced `ChatHomeFactory`, because the `ChatHome`s are instanciated
by `ChatBackendConfiguration`, which is not aware of the configured
implementation.
- Adjusted the test-cases to the changes.
- Added `InMemoryWithFilesAndShardingConfigurationIT`, that asserts,
that the application works as expected, if sharding is activated.
Kai Moritz [Fri, 13 Jan 2023 20:44:02 +0000 (21:44 +0100)]
test: Streamlined the config-IT, so that they use the same expectations
- Both tests now use the same data and expect the same results.
- Moved the actual tests and assertions to `AbstractConfigurationIT`.
- Also streamlined `AbstractStorageStrategyIT`, so that it produces
the exact same data, that the configuration-tests are expecting.
This is not a necessary change to get the refined coniguration-tests
running. It just makes it easier, to produce the needed test-data for
future refinements.
- Also streamlined the naming of the directory, where
`InMemoryWithFilesStorageIT` stores its data.
Kai Moritz [Fri, 13 Jan 2023 20:29:29 +0000 (21:29 +0100)]
refactor: Tried to simplify & clearify the naming of the integration-tests
Kai Moritz [Fri, 13 Jan 2023 19:37:36 +0000 (20:37 +0100)]
refactor: DRY für shard-selection
Kai Moritz [Thu, 12 Jan 2023 22:40:12 +0000 (23:40 +0100)]
feat: Prepared the application for sharding
- The `ChatBackendController` stores the `ChatHome`s in an array.
- Reintroduced a `ChatRoomFactory`
Kai Moritz [Wed, 11 Jan 2023 22:07:42 +0000 (23:07 +0100)]
test: Added integration-test `InMemoryWithMongoDbStorageIT`
Kai Moritz [Thu, 12 Jan 2023 21:58:56 +0000 (22:58 +0100)]
fix: Supressed mongo-autoconfiguration if `FilesStorageStrategy` is active
Kai Moritz [Thu, 12 Jan 2023 22:06:10 +0000 (23:06 +0100)]
refactor: Renamed the test to `InMemoryWithFilesStorageIT`
Kai Moritz [Wed, 11 Jan 2023 20:55:07 +0000 (21:55 +0100)]
feat: Refined `ChatBackendApplicationTest`
- Switched to a full server-startup (no MockMvc).
- Added some requests, that check the availability of the expected data.
Kai Moritz [Wed, 11 Jan 2023 20:41:46 +0000 (21:41 +0100)]
refactor: refined the endpoint-uri's
Kai Moritz [Wed, 11 Jan 2023 18:09:53 +0000 (19:09 +0100)]
feat: Introduced config switches to choose the used implementations
- Switched the existing `@Configuration`-classes into an auto-configuration.
- Added a `@ConditionalOnProperty`, that loades the default-configuration.
- Added an Auto-Configuration for the `MongoDbStorageStrategy`, which is
inactive by default and can be switched on by the property
`chat.backend.storage` to `mongodb`.
Kai Moritz [Wed, 11 Jan 2023 17:38:39 +0000 (18:38 +0100)]
feat: configuration for service & storage lives in the according packages
Kai Moritz [Tue, 10 Jan 2023 23:18:24 +0000 (00:18 +0100)]
test: Activated the maven-failsafe-plugin
Kai Moritz [Tue, 10 Jan 2023 22:59:36 +0000 (23:59 +0100)]
fix: Added constraints for valid usernames
- This fix is necessary, because not all usernames can be stored in
the newly introduced `MongoDbStorageStrategy`.
Kai Moritz [Mon, 9 Jan 2023 21:49:44 +0000 (22:49 +0100)]
feat: Implemented and tested `MongoDbStorageStrategy`
- Beware: The version 4.0.0 of Spring Data MongoDB that is included in
Spring Boot 3.0.x does not work with version 4.8.1 of the MongoDB drivers
that are included. Therefore, the version of the drivers was downgraded
to 4.7.2 - See:
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#compatibility.matrix
- Also tried an upgrade of Spring Boot from 3.0.0 to 3.0.1, but without
luck.
- Beware: Spring Boot 3.x does not include an autoconfigured embedded
version of MongoDB for testing. It removed the autoconfiguration for
`de.flapdoodle.embed:de.flapdoodle.embed.mongo` !
Kai Moritz [Mon, 9 Jan 2023 21:46:42 +0000 (22:46 +0100)]
refactor: Refined (simplified) `StorageStrategy`
Kai Moritz [Mon, 9 Jan 2023 21:42:37 +0000 (22:42 +0100)]
refactor: Moved `FilesStorageStrategy` in its own package -- Rename