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

Emit stream value after calling a method annotated with @Query(...) #383

Open
xzhorikx opened this issue Jul 27, 2020 · 4 comments
Open

Comments

@xzhorikx
Copy link

xzhorikx commented Jul 27, 2020

Greetings!

According to documentation, DAO methods annotated with @Query won't emit new values into the stream

Only methods annotated with @insert, @update and @delete trigger Stream emissions. Inserting data by using the @Query() annotation doesn't.

TL;DR in the end

I have the following situation:

  • Entity has 2 primary ID fields (id_local, id_remote)
  • When the entity is being sent to the remote source, its values are [id_local: "id_local", id_remote: null]
  • When the response is received, the entity has following values: [id_local: "id_local", id_remote: "id_remote"]
  • I need to set id_remote: "id_remote" to the entity that has id_local: "id_local"
  • If @Update is used, there will be no updated entity because there is yet no entity with [id_local: "id_local", id_remote: "id_remote"] primary keys
  • If @inesrt is used, then 2 entities will be created (since it has two primary keys):
1.   [id_local: "id_local", id_remote: null]
2.   [id_local: "id_local", id_remote: "id_remote"]
  • I cannot delete the entity with [id_local: "id_local", id_remote: null] primary keys because it will trigger unnecessary UI update (remove the old entity, add the new one)

To get my stream updated it's necessary to implement a dirty hack that calls @update method that updates nothing and whose sole purpose is to trigger stream data population:


// OBSERVERING STREAM HERE
class MyWidget {
  ...
  return StreamBuilder<List<Entity>>(
    stream: myRepo.findAll()
    builder: (context, entityList){
       updateState(entityList) <---- This expected to be trigerred after @Query(...) in dao is executed
    }
  )
}

@Dao
abstract class MyDao {
  @Query(update my_entity set remote_id = :remoteId where local_id = :localId)
  Future<void> updateRemoteId(remoteId, localId);
  
  @update
  update(Entity entity)
}

class MyRepo {
  MyDao myDao = database.getMyDao()
  
  Stream<List<Entity>> findAll() {
    return myDao.findAll();
  }

  void sendToRemote(entity){
    ..
    myDao.updateRemoteId(localId, remoteId)       <--- this is not triggering findAll() because @Query is used
    Entity entity = myDao.findById(entity.localId)  <--- looking for already updated entity
    myDao.update(entity)                            <--- dirty hack to trigger stream data update in observed findAll()
  }
}

So TL;DR question summary:

What is the best practice to trigger Stream data update after @Query(update set ... where ...) is executed? Would it be possible to add some kind of attribute to @Query annotation that would forcefully trigger stream data to be updated for all observers? I.e. @Query(emitData = true, "update set value =: value where id = :id")

@mqus
Copy link
Collaborator

mqus commented Jul 27, 2020

This feature is currently worked on in #361 and will work in the following way: floor will parse your sql statement in @Query and will then determine by itself which tables are updated. This work is mostly done, some tests are missing and it wasn't reviewed yet, but you can try it out right now by checking out the branch locally. (as this is the third issue that needs this PR we should maybe speed it up a little ;) )

If you want to keep using the current stable version then your current workaround is exactly what I would suggest. Although I would put it into a @transaction to avoid data races.

Originally I would have recommended you to do a @delete and @insert inside a transaction. Although this will trigger the Stream two times (due to #360 ), it should not show the intermediate state where the old entry was deleted and the new one was not yet added, because the transaction is only applied atomically.

@xzhorikx
Copy link
Author

Thank you for your response! Since this issue is now referenced in the PR you might close the issue if you feel like it.

@xzhorikx
Copy link
Author

Greetings @mqus
Are there any updates or ETA on this particular future implementation? Thanks!

@vitusortner
Copy link
Collaborator

We're still working on it and as you might know, giving ETAs in software projects is tricky.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants