Multiple data sources

Let's see how we can add multiple data sources and what happens when data is requested.

// Create validators
Validator<UsersRes> ageValidator = AgeValidator.create(TimeUnit.MINUTES.toMillis(2));
Validator<UsersRes> persistentDiskValidator = (key, item) -> Objects.nonNull(item) && !item.getItems().isEmpty();
// Builds an instance of Livebox using LiveboxBuilder class.
Livebox<UsersRes, Users> usersBox = new LiveboxBuilder<UsersRes, Users>()
.withKey("get_users")
.fetch(api::getUserList, UsersRes.class)
.addSource(Sources.MEMORY_LRU, ageValidator)
.addSource(Sources.DISK_PERSISTENT, persistentDiskValidator)
.addConverter(UsersRes.class, usersRes -> Optional.of(Users.fromUsersRes(usersRes)))
.retryOnFailure()
.build();

In this example we add two data sources to Livebox instance. This is what happens when the client subscribes the observable.

  1. We iterate the list of data sources and ask each one if they have data stored for key "get_users". Iteration is done by added order, so in the above example we first ask in-memory LRU data source and then disk persistent data source.

  2. If no data source has data available fetcher instance is called to fetch data.

  3. When a data source has available data, then call the data source validator to check if the data is still valid. Maybe the data is too old, or is not valid anymore for some other reason. If data is available and it's valid its emitted by the Observable.

When the option .refresh() is used, even if there's valid data stored locally we still hit the server to refresh it. In this case the Observable will emit twice, first with the local data, that can be used to immediately show content to the user and then with remote data received from fetcher.