Repository

A Repository is a class responsible of redirecting get/put/delete actions to one or many DataSources. This redirect semantic is encapsulated in Operation objects.

A good example of Repository is the CacheRepository, which depending on the Operation used on each request can obtain data from an storage-based data source or from a main-based data source. The most basic repository is the SingleDataSourceRepository which redirects all calls to the single data source that encapsulates.

Usage

val networkDataSource = MyNetworkDataSource()
val storageDataSource = MyStorageDataSource()
val repository = NetworkStorageRepository(networkDataSource, networkDataSource, networkDataSource, storageDataSource, storageDataSource, storageDataSource)
val future = repository.get(IdQuery("my-key"), StorageSyncOperation)

Operation

The Operation object itself defines intrinsically how a query must be forwarded to a data source, containing inside all parameters required to execute the action.

For more information, read the Operation reference.

API

The Repository functions replicate the DataSource public API, adding an extra parameter of type Operation on each function.

Get

Fetch related functions.

interface GetRepository<V> : Repository {
fun get(query: Query, operation: Operation = DefaultOperation): Future<V>
fun getAll(query: Query, operation: Operation = DefaultOperation): Future<List<V>>
}

Put

Actions related functions.

interface PutRepository<V> : Repository {
fun put(query: Query, value: V?, operation: Operation = DefaultOperation): Future<V>
fun putAll(query: Query, value: List<V>? = emptyList(), operation: Operation = DefaultOperation): Future<List<V>>
}

Delete

Deletion related functions.

interface DeleteRepository : Repository {
fun delete(query: Query, operation: Operation = DefaultOperation): Future<Unit>
fun deleteAll(query: Query, operation: Operation = DefaultOperation): Future<Unit>
}

IdQuery CRUD extensions

Similar to the DataSource public interface, all GetRepository, PutRepository and DeleteRepository interfaces are extended with methods to access the CRUD functions by an Id:

fun <K, V> GetRepository<V>.get(id: K, operation: Operation = DefaultOperation): Future<V> = get(IdQuery(id), operation)
fun <K, V> GetRepository<V>.getAll(ids: List<K>, operation: Operation = DefaultOperation): Future<List<V>> = getAll(IdsQuery(ids), operation)
fun <K, V> PutRepository<V>.put(id: K, value: V?, operation: Operation = DefaultOperation): Future<V> = put(IdQuery(id), value, operation)
fun <K, V> PutRepository<V>.putAll(ids: List<K>, values: List<V>? = emptyList(), operation: Operation = DefaultOperation) = putAll(IdsQuery(ids), values, operation)
fun <K> DeleteRepository.delete(id: K, operation: Operation = DefaultOperation) = delete(IdQuery(id), operation)
fun <K> DeleteRepository.deleteAll(ids: List<K>, operation: Operation = DefaultOperation) = deleteAll(IdsQuery(ids), operation)

This way, code that originally looked like this:

repository.get(IdQuery("myKey"))
repository.put(IdQuery("myKey"), myObject)
repository.delete(IdQuery("myKey"))

can be written as follows:

repository.get("myKey")
repository.put("myKey", myObject)
repository.delete("myKey")

Repository Implementations

Swift exclusive implementations

  • RepositoryAssembler<T>: Combines three repositories (get, put, delete) into a single object.
  • AnyRepository<T>: Type erasing for any get+put+delete repository.
  • AnyGetRepository<T>: Type erasing for a get repository.
  • AnyPutRepository<T>: Type erasing for a put repository.
  • RetryRepository<T>: Encapsulates another repository and retries a call when an error happens.

Swift Notes

Repository base protocol

In order to have a generic type, all GetRepository, PutRepository and DeleteRepository extends from the following base protocol:

public protocol Repository { }

Kotlin Notes

Repository base interface

interface Repository