當使用Objectify嘗試加載給定類型的所有實體時,我遇到了不一致。當獲得給定類型的所有實體(本地雲端點)時,物化不一致性
我運行一個雲端點後端本地,並使用下面的方法來填充數據存儲的設置:
public static void dsUp() {
Store store1 = new Store("H&M", new GeoPt(new Float(56.157702), new Float(10.206938)));
Store store2 = new Store("Marc Jacobs", new GeoPt(new Float(56.158284), new Float(10.208618)));
Store store3 = new Store("Weekday", new GeoPt(new Float(56.158522), new Float(10.207547)));
ofy().save().entities(store1, store2, store3).now(); // Synchronous save to auto generate id
}
建立數據庫後,數據存儲查看器顯示三個對象創建:
問題
我開始注意到,我的客戶端應用(iOS),有時只收到兩家店:
我重新在後端我getStores()方法,並改變它,使它加載所有商店4次,記錄每次嘗試,並最終返回第一次嘗試的結果。
的方法(將其更改爲多個負載嘗試後),看起來是這樣的:
public static List<Store> getStores() {
List<Store> result = ofy().load().type(Store.class).list();
LOGGER.warning("Getting Stores, try 1: " + result.toString());
LOGGER.warning("Getting stores, try 2: " + ofy().load().type(Store.class).list());
LOGGER.warning("Getting stores, try 3: " + ofy().load().type(Store.class).list());
LOGGER.warning("Getting stores, try 4: " + ofy().load().type(Store.class).list());
return result; // Returning the results from try 1
}
通常情況下,每一個試圖返回所有三家分店。但是,有時第一次嘗試,甚至第二次嘗試只會返回兩個商店。通過第三次和第四次嘗試,所有商店都被退回。
其中一個方法調用的記錄輸出如下所示。請注意,這次嘗試1和2只返回兩個商店。
我不能看到其存儲在數據庫重置之間留出任何圖案。有時它是一個,有時是另一個。然而,似乎在getStores()的同一調用中,如果嘗試1和2都失敗,它似乎缺少同一商店(如上圖所示)。
我試過了什麼?
我最初的想法是,我必須設置錯誤的Objectify過濾器。然而,據我所知,這似乎是有序的。在我的webapp/WEB-INF/web中。xml文件,我有以下的過濾器和過濾器映射:
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我不是很熟悉物化的緩存,但我試過如下:
添加以下行作爲第一件事情我getStores()在後端方法,加載任何實體之前:
ofy().clear(); // Clear the cache
我還加載實體在使用強一致性試過,如下:
List<Store> result = ofy().consistency(ReadPolicy.Consistency.STRONG).load().type(Store.class).list();
其他信息,可能是相關
我可以重新創建不一致,並且出現約1/5倍。但是,據我所知,它只發生在從頭開始設置數據庫後,使用前面提到的dsUp()方法。
嘗試之間,我用下面的方法來清除數據庫:
public static void dsDown() {
List<Key<Store>> allStoreKeys = ofy().load().type(Store.class).keys().list();
ofy().delete().keys(allStoreKeys).now();
}
至於數據存儲瀏覽器而言,dsDown()方法按預期工作,並保持數據庫空。據我所知,直接在Database Viewer中刪除實體可能會導致緩存未被刪除的問題。不過,我已經讀過,像在dsDown()方法中那樣使用Objectify刪除實體可以避免這個問題。
如果有任何其他信息我應該提供,請讓我知道。
謝謝!
EDIT(我的執行的解決方案,從@saiyr):
由於@saiyr指出,在本地運行時,這引起了不一致的數據存儲模擬最終一致性。以下屏幕截圖顯示了我如何將標誌添加到我的後端模塊的build.gradle文件中。
注:請注意,如果將模擬的最終一致性完全關閉(將標誌設置爲0)可能會導致Objectify事務出錯。這就是爲什麼我將標誌設置爲1的原因。有關詳細信息,請參閱this stack overflow post。
你想的標誌添加到後端項目的build.gradle文件:
這是否僅在將實體添加到數據存儲之後纔會發生? –
@EricSimonton我只在使用dsUp()方法設置數據庫之後才測試過,而沒有花費太多時間。但是,我也通過設置數據庫來測試它,然後在嘗試獲取所有實體之前,從客戶端(iOS應用程序)創建實體。這導致了類似的不一致,看起來完全是隨機的,不管實體/實體是用dsUp()方法創建的還是從應用程序創建的。你認爲我應該在獲得實體之前通過測試嗎? – jonasjuss