feroult / yawp

Kotlin/Java API framework for Google Appengine
http://yawp.io
MIT License
132 stars 20 forks source link

Bug in method frist() or limit(1) #39

Closed TomasSQ closed 8 years ago

TomasSQ commented 8 years ago

When executing:

yawp(Extrato.class).where("contaCorrenteFisicaId", "=", contaCorrenteFisica).and("data", "=", LocalDate.now().minusDays(1).toDate())
.first()

Returns null.

yawp(Extrato.class).where("contaCorrenteFisicaId", "=", contaCorrenteFisica).and("data", "=", LocalDate.now().minusDays(1).toDate()).limit(1)
.list()

Returns empty list.

yawp(Extrato.class).where("contaCorrenteFisicaId", "=", contaCorrenteFisica).and("data", "=", LocalDate.now().minusDays(1).toDate())
.limit(2).list()

Returns a list with one Extrato.

In the datastore, I have saved two Extrato's instances, with same "data" (java.util.Date), and diferents "contaCorrenteFisicaId" (IdRef).

feroult commented 8 years ago

@TomasSQ,

Which version of yawp are you using?

Can you show me the mappings for the endpoint attributes? They both have @Index annotation?

Can you also show me how the LocalDate creates dates?

Thanks!

TomasSQ commented 8 years ago

Version: 1.2.8

Extrato mapping:

@Endpoint(path = "/extratos")
public class Extrato {

    @Id
    private IdRef<Extrato> id;

    @Index
    private IdRef<Arrecadacao> arrecadacaoId;
    @Index
    private IdRef<ContaCorrenteFisica> contaCorrenteFisicaId;

    @Index
    private Date data;

    ...
}

LocalDate belongs to org.joda's api. The follow link has the code responsible for creating dates of a LocalDate's instance http://grepcode.com/file/repo1.maven.org/maven2/joda-time/joda-time/2.8.1/org/joda/time/LocalDate.java#LocalDate.toDate%28%29

feroult commented 8 years ago

I'm failing to reproduce. I'm trying with this test. Please check if it is similar:

(next step is to try with the joda-time dependency)

@Test
public void testLimitProblem() {
    long time = System.currentTimeMillis();

    BasicObject object1 = new BasicObject();
    object1.setObjectId(IdRef.create(yawp, BasicObject.class, 1l));
    object1.setDateValue(new Date(time));
    yawp.save(object1);

    BasicObject object2 = new BasicObject();
    object2.setObjectId(IdRef.create(yawp, BasicObject.class, 2l));
    object2.setDateValue(new Date(time));
    yawp.save(object2);

    assertNotNull(yawp(BasicObject.class).where("objectId", "=", IdRef.create(yawp, BasicObject.class, 1l)).and("dateValue", "=", new Date(time)).first());
}
TomasSQ commented 8 years ago

Yes, it is similar. The differences I see are: Extrato has IdRef to another class, not to itself, so the datastore has more objects saved; The use of joda-time; Our date has no time (hours, minutes, seconds, milliseconds are all set as zero), in theory;

When I debugged my test, sometimes executeQuery(); (DataStoreQuery.java: line 198 in my version) returned properly, but only few times.

luanpotter commented 8 years ago

@TomasSQ, Is it possible that this is due to Google Datastore eventual consistency? If you just added the records, there is no guarantee they will be available to you. And there is no exact definition of 'just'. Hahahaha

TomasSQ commented 8 years ago

It is possible that this is due to Google Datastore eventual consistency, but it's weird it only happens in this scenario in my project. Happened everytime I ran this specifics tests, and often when debugging.

feroult commented 8 years ago

Thanks @TomasSQ. I'm considering this is due eventual consistency. If you find this again, please report.