I am trying to understand how to properly use the ...
# server
d
I am trying to understand how to properly use the Repository pattern when creating a backend server. Should its functions be strictly CRUD like, or is it acceptable to have some use-case-specific "logic" related to the Entities it works represented there? For example, is this something I should rather split?
Copy code
sealed class Event {
    abstract val receivedAt: Instant
    abstract val occurredAt: Instant
    ...

    data class Incoming(
        override val receivedAt: Instant,
        override val occurredAt: Instant,
        ...
    ) : Event()

    sealed class Stored : Event() {
        abstract val authorUid: ULong

        data class Pending(
            override val receivedAt: Instant,
            override val authorUid: ULong,
            override val occurredAt: Instant,
           ...
        ) : Stored()

        data class Uploaded(
            override val receivedAt: Instant,
            override val authorUid: ULong,
            override val occurredAt: Instant,
            ...
            val uploadedAt: Instant
        ) : Stored()
    }
}

interface EventRepository {
    fun storeEvent(authorUid: ULong, event: Event.Incoming): Event.Stored.Pending
    fun confirmEvent(event: Event.Stored.Pending, uploadTime: Instant = Instant.now()): Event.Stored.Uploaded
    fun getEvents(): Collection<Event.Stored>
    fun getEventsCount(): ULong
    fun pendingEvents(): Collection<Event.Stored.Pending>
    fun pendingEventsCount(): ULong
}
a
Rule of thumb is to keep business logic out, yes. Here's some thoughts: storeEvent So long as the logic to construct the event is very simple, you can keep it as is. Otherwise, I suggest you pass in the
Event
to insert. confirmEvent I'm assuming what you're doing is searching for an event at a specific time. To make it less business-specific, you can just rename to
getEvent
and then have the outer business logic infer the event is confirmed Otherwise, looks fine to me.