我們有一個數據集,它在應用程序處理數據集時會增長。經過漫長的討論後,我們決定暫時不需要阻塞或異步API,我們會定期查詢我們的數據存儲。查詢日益增長的數據集
我們認爲兩個選項來設計的API進行查詢我們的存儲:
- 的查詢方法返回的數據和指示天氣,我們可能有更多的數據的標記的快照。當我們完成對最後一次返回的快照的迭代時,我們再次查詢以獲取其他數據的另一個快照。
- 查詢方法返回數據上的「實時」迭代器,當此迭代器前進時,它將返回以下選項之一:數據可用,不再有數據,可能有更多數據。
我們使用C++,並且因爲這個問題的範圍超出了原因,我們借用了.NET樣式枚舉器API。這裏有一些代碼來演示這兩種選擇。你更喜歡哪個選項?
/* ======== FIRST OPTION ============== */
// similar to the familier .NET enumerator.
class IFooEnumerator
{
// true --> A data element may be accessed using the Current() method
// false --> End of sequence. Calling Current() is an invalid operation.
virtual bool MoveNext() = 0;
virtual Foo Current() const = 0;
virtual ~IFooEnumerator() {}
};
enum class Availability
{
EndOfData,
MightHaveMoreData,
};
class IDataProvider
{
// Query params allow specifying the ID of the starting element. Here is the intended usage pattern:
// 1. Call GetFoo() without specifying a starting point.
// 2. Process all elements returned by IFooEnumerator until it ends.
// 3. Check the availability.
// 3.1 MightHaveMoreDataLater --> Invoke GetFoo() again after some time by specifying the last processed element as the starting point
// and repeat steps (2) and (3)
// 3.2 EndOfData --> The data set will not grow any more and we know that we have finished processing.
virtual std::tuple<std::unique_ptr<IFooEnumerator>, Availability> GetFoo(query-params) = 0;
};
/* ====== SECOND OPTION ====== */
enum class Availability
{
HasData,
MightHaveMoreData,
EndOfData,
};
class IGrowingFooEnumerator
{
// HasData:
// We might access the current data element by invoking Current()
// EndOfData:
// The data set has finished growing and no more data elements will arrive later
// MightHaveMoreData:
// The data set will grow and we need to continue calling MoveNext() periodically (preferably after a short delay)
// until we get a "HasData" or "EndOfData" result.
virtual Availability MoveNext() = 0;
virtual Foo Current() const = 0;
virtual ~IFooEnumerator() {}
};
class IDataProvider
{
std::unique_ptr<IGrowingFooEnumerator> GetFoo(query-params) = 0;
};
更新
鑑於目前的答案,我有一些澄清。辯論主要在於界面 - 它的表現力和直觀性表現了對不斷增長的數據集的查詢,並在某個時間點停止增長。這兩個接口的實現是可能沒有競爭條件(AT-至少我們相信如此),因爲以下屬性:
- 首屆選項可以正確地實施,如果對迭代器+國旗代表的快照系統在查詢時。獲取快照語義不成問題,因爲我們使用數據庫事務。
- 第二個選項可以在第一個選項正確實現的情況下執行。第二個選項的「MoveNext()」將在內部使用類似第一個選項的內容,並在需要時重新發出查詢。
- 數據集可以從「可能有更多數據」更改爲「數據結束」,但反之亦然。因此,如果我們錯誤地因爲競爭條件返回「可能有更多數據」,我們只會得到一個小的性能開銷,因爲我們需要再次查詢,並在下一次我們將收到「數據結束」。
看到更新以上 – Alex
那麼你更喜歡第二個選項,與「活」迭代器? – Alex
@亞歷山大,那就是那個。乾杯。 –