The Validator is optional. If you don’t provide one, the Store defaults to considering the cached data valid.

Purpose of the Validator

  • Data Freshness: Ensures the data served to your application is up-to-date and meets your application’s specific validity criteria.
  • Optimizing Network Usage: Prevents unnecessary network calls by using valid cached data when appropriate.
  • Consistency Control: Gives you fine-grained control over when to refresh data, enhancing consistency between the client and server.

APIs

Validator

Validator has the following structure:

interface Validator<Output : Any> {
    suspend fun isValid(item: Output): Boolean
}
Output
Any
required

The type representing your domain data model. For example, if you have a Store<Int, Post>, the Output is Post.

isValid(item: Output)
Boolean

A suspending function that determines whether the given item is still valid.

Data Flow

1

Data Retrieval Request

When your application requests cached data from the Store, it first checks the Memory Cache and the Source of Truth to see if the data is available.

The Validator only operates on data from the Source of Truth and does not validate data coming directly from the network.

2

Validation Check

The Validator’s isValid method is called with the cached data as the parameter.

3

Validity Determination

  • If isValid returns true, the Store considers the cached data valid and servies it to the application.
  • If isValid returns false, the Store deems the cached data invalid and proceeds to fetch fresh data from the remote source using the Fetcher.
4

Data Update

If new data is fetched, it’s stored in the Memory Cache and the Source of Truth for future requests.

Implementing a Validator

You can create a Validator using the Validator.by factory method:

val validator = Validator.by { item ->
    // Your custom validation logic here
}

Examples

Time-Based Validation

If your application has data that should be refreshed every 24 hours:

val validator = Validator.by { item ->
    Clock.System.now() < item.expiresAt
}

Versioning

If your application data model changes and you need to invalidate old cached data:

val validator = Validator.by { item ->
    item.version == CURRENT_VERSION
}

User Authentication

In cases where authentication tokens expire:

val validator = Validator.by { item ->
    !item.token.isExpired()
}

Best Practices

  • Keep Validation Logic Lightweight: The isValid function should execute quickly to avoid slowing down data retrieval. Complex computations or I/O operations should be avoided.
  • No Side Effects: The Validator should not modify the data or state. It should only assess the validity of the provided item.
  • Decide on Validity Criteria: Clearly define what makes data valid or invalid in your application’s context. This could be based on timestamps, data content, user preferences, or other domain-specific factors.