New app architecture #240
josecelano
started this conversation in
Proposals
Replies: 1 comment
-
Regarding extracting more packages in the workspace the aquatic BitTorrent tracker could be a case to study. We could even check which packages we could have in common. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi @da2ce7 @WarmBeer, I have created this diagram reflecting the current app architecture:
I want to use it to discuss some changes I want to propose.
But before proposing concrete changes, I will explain the current architecture and the drawbacks I think it has.
Current architecture
Some thing I thin we could improve are:
As you can see in the diagram, the Tracker has at least six responsibilities.
For the
authentication
,whitelist
, andcore tracker
, it handles the persistence too (persistence).And it's also responsible for constructing all those services (app container).
One advantage of this big class is you only need to pass it around to get access to all the services you need. For example, in the web handlers (Axum controllers), you only need one dependency: the tracker.
On the other hand, one of the drawbacks is that it's hard to test, or it makes it harder to test each responsibility independently.
For example, it would be much easier to test a "whitelist" service which is internally implemented with the
RwLock<std::collections::HashSet<InfoHash>>
. We could have two whitelist implementations the In-Memory implementation and the In-Database implementation.Deletaging subtasks to other services would make the code easier to test, to change and less coupled.
The tracker is also responsible for handling the authentication keys. But authentication keys are used only by the HTTP tracker app. They do not make sense for the UDP tracker or the tracker API.
Short-term changes
I've started introducing new layers to the app architecture. For example, the HTTP tracker now has a service layer:
This service is responsible for calling the domain service
Tracker::announce
orTracker::scrape
and sending the statistics events. Events are sent at this level because events are specific for the UPD or HTTP tracker. Maybe in the future, we could have generic events with an attribute. Instead of:We could have:
Although I've introduced these new services, there is still a lot of code in the Axum handlers that could potentially be moved to the service because it does not depend on Axum, and it could be reused if we change Axum. For example:
The
announce handler
:As you can see, the handler does three actions:
Those tasks are there because they were also there before migrating to Axum and because we return a custom response, and the HTTP response is something that should not be in the App service.
One of my proposals is to move that code inside the service. The service only returns an App error, and the handler captures the error and builds the right custom response.
The final handler would be like this:
NOTE: I've also started using the
authorisation
term. Right now, the only authorization is the whitelist. Once you are authenticated, we check if the tracker is whitelisted and if the torrent is in the whitelist. Although now authorization means whitelist, I've introduced the generic authorization layer that happens to use a whitelist under the hood. In the future, we could define permissions for categories, for example.Middle-term changes
In the middle-term we do two things:
whitelist
,authorization
Long-term changes
In the long term, we could discuss it again about persistence. Right now, we are handling both: in-memory objects and DB records and the same time, but they are independent. The tracker should work without persistence. For example, when we generate a new key, we keep it in memory, and we also store it in the DB. The DB is only used to recover backups. Somehow the source of truth is the memory, and the DB is just a backup that is synced in real-time.
I would introduce services that handle both in-memory collections and persistence. For example:
WhitelistService
-uses->InMemoryWhitelistRepository
,DbWhitelistRepository
The
WhitelistService
uses the DbWhitelistRepository only if persistence is enabled.Beta Was this translation helpful? Give feedback.
All reactions