Objectify:如何禁用会话缓存?

时间:2016-02-05 15:51:45

标签: google-app-engine objectify google-cloud-datastore

我喜欢Objectify的“只是使用ofy()”方便来获得一个Objectify实例,但我遇到了一个用例,我可以使用一些建议。

我的数据存储区的用例是,在我的过程的一部分中,我将在长时间运行的过程中编写实体。成千上万的实体。它们将分散在时间/实体组中(因此数据存储区争用对我来说并不是一个问题)。在这个长时间运行的过程中,我不需要读取数据存储区实体一次。

我知道我可以通过使用Objectify.cache(false)来创建一个不使用memecache的实例来禁用“二级”缓存。那很好。

我关心的是会话缓存。我只是稍微窥视了Objectify代码,当我们为我们遇到的实体执行“save()”时,似乎在WriteEngine.java中:

                // Also stuff this in the session
                session.addValue(key, obj);

所以客观化是在记忆中抓住我的物品?我想在任何可能的缓存中关闭保存实体。

2 个答案:

答案 0 :(得分:2)

所以要明确...... @stickfigure的答案是标准Objectify的明确答案。我希望他能查看这段代码并发表评论。而且我希望Objectify将来可能有更多的缓存选项......甚至可能在实体层面!在那之前,下面是我正在使用的黑客,也许其他人会觉得有用。

那些如果你曾经使用过Objectify一段时间的人可能会记住这个服务模型的想法。您可以通过包含

来使用此OfyService
import static com.industryopenings.seeker.shared.OfyService.ofyw;

在班级的顶部。然后,您只需拨打ofyw(),通常会拨打ofy()。请注意...... ofyr()ofyw()的混合不是我对此代码的意图。混合可能会产生奇怪的结果。特别是在交易中。

OfyService有两件事......

  1. 确保使用Objectify创建的ofyw()实例具有cache(false)规范而不是默认cache(true)
  2. clear()来电OFYW_USE_COUNT_THRESHOLD
  3. 后,定期为您调用ofyw()方法

    请记住,我们没有太多能力来检查客观化会话......这里没有对象大小或对象计数逻辑。它假定您定期调用ofyw()(不保留Objectify实例)并且只是为您定期清除会话。

    import com.googlecode.objectify.*;
    import com.googlecode.objectify.impl.ObjectifyImpl;
    
    public final class OfyService {
        public final static int OFYW_USE_COUNT_THRESHOLD = 10;
        public static int currentReferenceCount = 0;
        private static ObjectifyFactory defaultFactory = new ObjectifyFactory();
        private static ObjectifyFactory noCacheFactory = new NoCacheFactory();
    
        // This factory always returns a no-cache instance.
        // BUT: end users can be foolish and turn it back on if they want... having potentially ripple effects downstream
        // Best practice if you're going to use this OfyService is to never call the cache(boolean) method
        private static class NoCacheFactory extends ObjectifyFactory {
            @Override
            public Objectify begin() {
                return new ObjectifyImpl<>(this).cache(false);
            }
        }
    
        // Note!  We probably need to register our classes in both factories
        static {
            defaultFactory.register(Doc.class);
            defaultFactory.register(SiteLogEntry.class);
            defaultFactory.register(SiteLogRunSummary.class);
    
            noCacheFactory.register(Doc.class);
            noCacheFactory.register(SiteLogEntry.class);
            noCacheFactory.register(SiteLogRunSummary.class);
        }
    
        // ofyr to get an Objectify... with the "r" to denote read / caching enabled.
        public static Objectify ofyr() {
            ObjectifyService.setFactory(defaultFactory);
            return ObjectifyService.ofy();
        }
    
        // ofyr to get an Objectify... with the "w" to denote writing / no caching enabled.
        public static Objectify ofyw(){
            // This will ensure we're not using second level cache (memecache)
            ObjectifyService.setFactory(noCacheFactory); 
    
            // In lieu of a true solution we're simply going to clean house every X times ofyw() is called
            currentReferenceCount++;
            Objectify o = ObjectifyService.ofy();
            if(currentReferenceCount > OFYW_USE_COUNT_THRESHOLD){
                o.clear();
                currentReferenceCount = 0;
            }
            return o;
        }
    }
    

    希望这有助于其他人。

答案 1 :(得分:1)

不幸的是,现在唯一的方法是定期拨打ofy().clear()。我看到你在github跟踪器中添加了一个问题,这很好。