ludoch / datanucleus-appengine

Automatically exported from code.google.com/p/datanucleus-appengine
0 stars 0 forks source link

L1 and L2 caching does not work for entities with namespaces #319

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Namespace is part of the primary key of every entity in the Datastore. 
Typically the namespace is empty, but some applications set this value.

The datastore considers the following two keys to be not equal:
1) Kind: Foo, Namespace: Bar1, Id: 23
2) Kind: Foo, Namespace: Bar2, Id: 23

However, it looks like the L1 and L2 caches don't take namespace into account. 
so if a request is executing under namespace Bar2 and we try to fetch Key 2 
from the cache, we can get back the entity identified by Key 1, which is 
incorrect.

Here's a test case that reproduces the issue with the L1 cache:

@PersistenceCapable(detachable = "true")
public class NamespaceYamJDO {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Long key;

  @Persistent
  private String ns;

  public Long getKey() {
    return key;
  }

  public void setKey(Long key) {
    this.key = key;
  }

  public String getNs() {
    return ns;
  }

  public void setNs(String ns) {
    this.ns = ns;
  }
}

public class JDOQLNamespaceTest extends JDOTestCase {

  public void testYar() {
    NamespaceManager.set("n1");
    try {
      for(int i = 0; i < 12; i++) {
        Entity e = new Entity("NamespaceYamJDO", i + 1);
        e.setProperty("ns", "n1");
        ds.put(e);
      }
    } finally {
      NamespaceManager.set(null);
    }

    NamespaceManager.set("n2");
    try {
      for(int i = 0; i < 12; i++) {
        Entity e = new Entity("NamespaceYamJDO", i + 1);
        e.setProperty("ns", "n2");
        ds.put(e);
      }
    } finally {
      NamespaceManager.set(null);
    }

    String query = "select from " + NamespaceYamJDO.class.getName();

    NamespaceManager.set("n1");
    try {
      List<NamespaceYamJDO> result = (List<NamespaceYamJDO>) pm.newQuery(query).execute();
      for (NamespaceYamJDO e : result) {
        System.out.println(e.getKey() + " " + e.getNs());
      }
    } finally {
      NamespaceManager.set(null);
    }

    NamespaceManager.set("n2");
    try {
      List<NamespaceYamJDO> result = (List<NamespaceYamJDO>) pm.newQuery(query).execute();
      for (NamespaceYamJDO e : result) {
        System.out.println(e.getKey() + " " + e.getNs());
      }
    } finally {
      NamespaceManager.set(null);
    }
  }
}

Original issue reported on code.google.com by max.r...@gmail.com on 22 May 2013 at 5:14

GoogleCodeExporter commented 8 years ago
> Namespace is part of the primary key

yet it isn't in your example, so the information isn't provided to the 
persistence mechanism

Original comment by googleco...@yahoo.co.uk on 22 May 2013 at 5:59

GoogleCodeExporter commented 8 years ago
Right. The namespace is this magical and implicit thing that you don't need to 
explicitly add to the Key when you're creating a new Entity. Once the Entity 
has been persisted, the namespace is set.

Original comment by max.r...@gmail.com on 23 May 2013 at 1:16