Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Skip any caches if network emits first. #179

Open
pardom opened this issue Jun 16, 2020 · 2 comments
Open

[Feature Request] Skip any caches if network emits first. #179

pardom opened this issue Jun 16, 2020 · 2 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@pardom
Copy link

pardom commented Jun 16, 2020

At present, fetcher emissions are locked until reader emits, in order to preserve emission order. This presents a problem in the case that you do not want to emit from reader for a given condition, but instead return an emptyFlow. In this case, fetcher will never emit because reader never emits.

A potential solution would be to add some sort of "disk required" property to StoreRequest in order to either enforce current the fetcher lock behavior or skip the reader emission in the case that fetcher emits first.

To work around this, I have moved the conditional logic in fetcher to a map on stream(). However, it would be ideal to instead provide this behavior as part of the library.

Here's an example of the above:

sealed class GetItemError {
  data class Missing(val itemId: ItemId): GetItemError()
  data class Failure(val error: Exception): GetItemError()
}

typealias GetItemResult = Either<GetItemError, Item>
typealias GetItem = (ItemId) -> Flow<GetItemResult>

val fetcher: GetItem =
  { itemId ->
    try {
      val item = itemApiService.getItemById(itemId)
      if (item != null) {
        flowOf(Right(item))
      } else {
        flowOf(Left(GetItemError.Missing(itemId)))
      }
    } catch(e: Exception) {
      flowOf(Left(GetItemError.Failure(e)))
    }
  }

val reader: GetItem =
  { itemId ->
    val item = itemDao.getItemById(itemId)
    if (item != null) {
      flowOf(Right(item))
    } else {
      // Return empty Flow instead of `GetItemError.Missing` because DB 
      // isn't populated yet and this is not an error case.
      emptyFlow()
    }
  }
@pardom pardom added the enhancement New feature or request label Jun 16, 2020
@pardom
Copy link
Author

pardom commented Jun 16, 2020

After exploring a bit more and becoming aware of the (Key) -> Flow<Output?> type of reader, I've discovered another workaround:

val dbGetItem: GetItem =
  { itemId ->
    val item = itemDao.getItemById(itemId)
    if (item != null) {
      flowOf(Right(item))
    } else {
      flowOf(Left(GetItemError.Missing(itemId))
    }
  }

val reader: (ItemId) -> Flow<GetItemResult?> =
  { itemId ->
    dbGetItem(itemId).map { result ->
      when (result) {
        is Either.Left -> when (result.a) {
          // Map GetItemError.Missing to null to skip disk
          is GetItemError.Missing -> null
          else -> result
        }
        is Either.Right -> result
      }
    }    
  }

Perhaps documentation is all that is needed to resolve this issue.

@digitalbuddha digitalbuddha added documentation Improvements or additions to documentation and removed enhancement New feature or request labels Jul 18, 2020
@digitalbuddha
Copy link
Contributor

digitalbuddha commented Jul 18, 2020

Thanks for reporting, we will indeed add this to the upcoming docs.

@digitalbuddha digitalbuddha self-assigned this Nov 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants