Traits as a means to implement a "Service" layer?

My scenario is an application that allows for different databases to be used for the datastore, one being Elastic and one being SQLite its beyond abstracting at the SQL layer, and it seems like traits for these datastore structs might make sense, but am curious if I'm missing a better option.. Basically what I'm looking at..

struct SQLiteDataStore {
    // Connection, and some basic methods for working with the datastore.
}

struct ElasticDataStore {
    // Connection, basic methods for working with the datastore.
}

And then an enum that is part of my shared state object that is passed to all my web handlers (this is an axum based app):

enum Datastore {
    SQLite(SQLiteDataStore),
    Elastic(ElasticDataStore),
}
/// The shared state passed to all route handlers.
struct SharedState {
    pub datastore: Datastore,
    ....
}

So one service might be a StatsService that generates a report from the datastore.

trait StatsService {
    async fn stats_by_agent(&self, ...) -> Result<...>;
}

And then implement that for each datastore, or even on the enum so my router handlers don't concern themselves with the type of datastore at all.

I had first started by adding all the things I might do with a datastore in the datastore impl itself, but thats getting a bit bloated as the application grows.

Thanks for any ideas or comments on this type of structure.

If you have an enum like Datastore, you don't really need the trait., you can just implement everything you need directly on the enum.

Thats essentially what I'm coming from but I'm trying to get away from an ever increasing impl block, as I can logically break up my methods into QueryService, AuthService, AaaService, BbbServer, etc. But they're all built on the underlying datastore.

You can also do this without traits by having multiple impl blocks tagged with comments.

Yeah, this might be the way, was just reading about the rules of putting impl blocks for the same struct into children modules, structurally the might be the simplest.

I think you are on the right track. Traits are a more suitable abstraction than enums in this case. The different repository implementations form a potentially open set, and they don't have anything to do with each other, so conceptually they are not really just the "either this or that" idea that enums represent.

The proper name for what you are trying to do is called the Repository Pattern. You can google that term to find out how it is usually implemented.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.