2

I'm using the newest version of realm, and have this inconsistency problem:

this line of code :

realm.where(Realm_Building.class).findAll()

return either a list of 166 elements or zero elements. I have a few tens of api requests using this code one after another without changing anything in the database.

what might be causing this?

EDIT:

this is the entire function:

public Building getBuilding(String buildingInternalId) {
    Building building = null;
    Realm realm = Realm.getInstance(realmConfig_data);
    Realm_Building realm_building  =     
       realm.where(Realm_Building.class).equalTo("internalId", 
       buildingInternalId).findFirst();
    if (realm_building != null){
        building = new Building(realm_building);
        building.setMachines(getMachines(building.getInternalId()));
    }
    return building;
}

this line - realm.where(Realm_Building.class).findAll() is in the watch. I get a list and check the size of it.

Maayan Castel
  • 133
  • 1
  • 13
  • We need more info. Can you post the entire code, also how you check the number of objects in the result? – Christian Melchior Nov 10 '15 at 10:04
  • Is it possible it's cause by multiple reads and writes at the same time? reads are from different thread, writes are from the same one. – Maayan Castel Nov 10 '15 at 12:51
  • Depending on how you update you read threads. Realm is an MVCC database which means that different consistent views of your data can be available at the same time. If you open a Realm on thread A and B at the same time and write on A, B will not see those changes until you call `realm.refresh()` on it. Looper threads will do that automatically, on non-looper threads you must do this yourself. – Christian Melchior Nov 10 '15 at 12:58
  • isn't Realm realm = Realm.getInstance(realmConfig_data) enough to get the latest view of the data? – Maayan Castel Nov 10 '15 at 13:28
  • Yes it is, but if both thread A and B calls `getInstance()` before A writes, then you have a scenario where A says it has 166 elements while B says it has 0. Each thread gets a consistent view when you open the Realm. – Christian Melchior Nov 10 '15 at 13:30
  • I think this in not the case for us, we call this function long time after persisting all the buildings, and nobody is deleting them. can you think of anything else that might cause this problem? – Maayan Castel Nov 10 '15 at 13:40
  • No, the only other possibility could be that maybe the transaction wasn't committed when you saved your data? I would suggest opening a ticket on our GitHub so we can investigate it a bit more: https://github.com/realm/realm-java/issues – Christian Melchior Nov 10 '15 at 13:43
  • Should I call realm.close() after every time I get a realm instance? or committing the change is enough? – Maayan Castel Nov 10 '15 at 14:51
  • 1
    You should close it when done on the thread. Otherwise you risk running out of memory – Christian Melchior Nov 10 '15 at 14:59
  • so is it possible we ran out of memory, the objects were collected and that what caused the zero elements in the list? – Maayan Castel Nov 10 '15 at 15:04
  • No, if you run out of memory Realm will crash completely. – Christian Melchior Nov 11 '15 at 07:20
  • Have you ever solved that problem? I am having data inconsistency too, and I am also writing and reading from different threads – Tooroop Sep 01 '16 at 09:23
  • @Tooroop that is common when you use a thread pool like `Schedulers.io()` but you are working outside of a transaction (or force a refresh) – EpicPandaForce Dec 16 '16 at 11:54
  • @EpicPandaForce you again haha :) We talked about that in another question where I solved the issue. http://stackoverflow.com/questions/39138108/realm-data-sync-not-consistent – Tooroop Dec 16 '16 at 12:02
  • ah, yeah, `Schedulers.newThread()` creates a new thread, so those threads never experience version retention. I do remember that one :P – EpicPandaForce Dec 16 '16 at 12:05

1 Answers1

0

You are most likely calling

public Building getBuilding(String buildingInternalId) {
    Building building = null;
    Realm realm = Realm.getInstance(realmConfig_data);

this method on a non-looper background thread, but you never actually close this Realm instance.

Therefore, your background thread will never release the Realm version it holds after opening its first instance, and will never be able to update. So you experience version retention.

Solution: open Realm at beginning of thread, close it at the end of thread.

Relevant docs: https://realm.io/docs/java/latest/#closing-realm-instances

// Run a non-Looper thread with a Realm instance.
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Realm realm = Realm.getDefaultInstance();
        try {
            // ... Use the Realm instance ...
        } finally {
            realm.close();
        }
    }
});

thread.start();

If all else fails, you can force a refresh after you obtain the instance.

Community
  • 1
  • 1
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428